import sys
import os
import csv
import xml.etree.ElementTree as ET
import pikepdf


class XfaObj(dict):
    def __init__(self, sourcePdf):
        self.source = sourcePdf
        self.root = self.source.Root.AcroForm.XFA
        self.xfaDict = {}
        
        for i,item in enumerate(self.root):
            if(i % 2 == 0 and isinstance(item,pikepdf.String)):
                #print(f'label {i}: {item}')
                label = f'{item}'
                self.xfaDict[label] = self.root[i+1]
        #this next line is way more important/useful than it appears!
        # it makes someone able to treat an XfaObj as a dict pretty much.
        super(XfaObj,self).__init__(self.xfaDict)
         

    def __getitem__(self,key):
        if(isinstance(self.xfaDict[key],pikepdf.Stream)):
            return self.xfaDict[key].read_bytes().decode('utf-8')
        else:
            print('xfa item detected was not a stream')
            return self.xfaDict[key]

    #note: pikepdf.Stream requires straight up bytes. 
    def __setitem__(self,key,value):
        if(isinstance(value,str)):
            value = bytes(value,'utf-8')
        self.xfaDict[key].write(value)

def pdf_analyser(file_path):
    try:
        with pikepdf.Pdf.open(file_path) as pdfData:
            xfaDict = XfaObj(pdfData)
            if 'datasets' in xfaDict:
                datasets = xfaDict['datasets']
                root = ET.fromstring(datasets)
                data = root.find('{http://www.xfa.org/schema/xfa-data/1.0/}data').find('data')
                
                if data.find('IM_P0002/YYID1') is not None:
                    if data.find('IM_T5FPBS4GT') is not None:
                        print(f"Analysis PN : '{file_path}'")
                        return pn_analizer(data)
                    else:
                        print(f"Analysis DN : '{file_path}'")
                        return dn_analizer(data)
    except:
        fail = True
    print(f"Error : '{file_path}' is not a valid file")
    return None

def pn_analizer(data):
    rank = data.find('IM_T5FPBS4GT/GCTXT').text
    lastname = data.find('IM_P0002/NACHN').text
    firstname = data.find('IM_P0002/VORNA').text
    nid = data.find('IM_P0002/YYID1').text

    data_nodes = data.findall('TEXTE/DATA/STRING')
    table_data = []
    for data_node in data_nodes:
        table_data.append(data_node.text)
    function_text = table_data[1] if table_data[1] is not None else ''
    pn = table_data[50] if table_data[50] is not None else ''
    notation_by = table_data[51] if table_data[51] is not None else ''
    date = table_data[53] if table_data[53] is not None else ''

    data_nodes = data.findall('IT_HRT1045_QSR/DATA')
    table_data = []
    for data_node in data_nodes:
        table_data.append(data_node.find('RATING').text)

    strong = 0
    normal = 0
    weak = 0
    for i in range(3, 7):
        if table_data[i] is not None:
            if int(float(table_data[i])) == 1:
                strong = strong + 1
            if int(float(table_data[i])) == 2:
                normal = normal + 1
            if int(float(table_data[i])) == 3:
                weak = weak + 1
    for i in range(7, 45):
        if table_data[i] is not None:
            if int(float(table_data[i])) == 1:
                strong = strong + 1
            if int(float(table_data[i])) == 2:
                weak = weak + 1

    ccpm = ''
    if table_data[47] is not None:
        match int(float(table_data[47])):
            case 1:
                ccpm = 5
            case 2:
                ccpm = 4
            case 3:
                ccpm = 3
            case 4:
                ccpm = 2
            case 5:
                ccpm = 1
            case 6:
                ccpm = 'NA'
            case 7:
                ccpm = 'Exempt'
    
    qsr = ''
    if table_data[49] is not None:
        match int(float(table_data[49])):
            case 1:
                qsr = 'XX'
            case 2:
                qsr = 'A'
            case 3:
                qsr = 'B'
            case 4:
                qsr = 'C'
            case 5:
                qsr = 'D'
            case 6:
                qsr = 'E'
            case 7:
                qsr = 'F'

    return (nid, rank, lastname, firstname, function_text, strong, normal, weak, ccpm, qsr, pn, notation_by, date)

def dn_analizer(data):
    nid = data.find('IM_P0002/YYID1').text

    data_nodes = data.findall('TEXTE/DATA/STRING')
    i = 0
    table_data = []
    for data_node in data_nodes:
        table_data.append(data_node.text)
        i = i+1
    dn = table_data[3] if table_data[3] is not None else ''
    notation_by = table_data[5] if table_data[5] is not None else ''
    date = table_data[7] if table_data[7] is not None else ''

    data_nodes = data.findall('IT_HRT1045_QSR/DATA')
    table_data = []
    for data_node in data_nodes:
        table_data.append(data_node.find('RATING').text)

    apt = ''
    if table_data[1] is not None:
        match int(float(table_data[1])):
            case 1:
                apt = 'IMM'
            case 2:
                apt = 'AT'
            case 3:
                apt = 'INC'
    pot = ''
    if table_data[2] is not None:
        match int(float(table_data[2])):
            case 1:
                pot = 'OUI'
            case 2:
                pot = 'AT'
            case 3:
                pot = 'NON'
    
    rac = ''
    if table_data[4] is not None:
        match int(float(table_data[4])):
            case 1:
                rac = -2
            case 2:
                rac = -1
            case 3:
                rac = 0
            case 4:
                rac = 1
            case 5:
                rac = 2

    return (nid, rac, apt, pot, dn, notation_by, date)


def explore_directory(directory_path):
    pn = []
    dn = []
    for root, _, files in os.walk(directory_path):
        for file in files:
            file_extension = file.split('.')[-1]
            if file_extension == 'pdf':
                file_path = os.path.join(root, file)
                n = pdf_analyser(file_path)
                if n is not None:
                    if len(n) == 13:
                        pn.append(n)
                    elif len(n) == 7:
                        dn.append(n)
    return (pn, dn)

def mix_pn_dn(pn_source, dn_source):
    mix = []
    for p in pn_source:
        for d in dn_source:
            if p[0] == d[0]:
                mix.append(p[:10] + d[1:4] + p[10:] + d[4:])
    pn_dn = len(mix)
    print(f"{pn_dn} PN and DN")
    for p in pn_source:
        is_mix = False
        for m in mix:
            if p[0] == m[0]:
                is_mix = True
                break
        if not is_mix:
            mix.append(p[:10] + ('', '', '') + p[10:] + ('', '', ''))
    pn = len(mix) - pn_dn
    if pn > 0:
        print(f"{pn} only PN")
    for d in dn_source:
        is_mix = False
        for m in mix:
            if d[0] == m[0]:
                is_mix = True
                break
        if not is_mix:
            mix.append(d[:1] + ('', '', '', '', '', '', '', '', '') + d[1:4] + ('', '', '') + d[4:])
    dn = len(mix) - pn_dn - pn
    if dn > 0:
        print(f"{dn} only DN")
    return mix


def save_to_csv(mix, csv_file):
    with open(csv_file, 'w', newline='') as csvfile:
        writer = csv.writer(csvfile, delimiter=';')
        writer.writerow(['NID', 'Grade', 'Nom', 'Prénom', 'Emploi tenu', 'Compétences fort', 'Compétences normal', 'Compétences perfectible', 'CCPM', 'QSR', 'RAC', 'Aptitude', 'Potentiel', 'PN', 'par', 'date', 'DN', 'par', 'date'])
        writer.writerows(mix)
    print(f"'{csv_file}' generated with all data")


def clean_ds_store(directory_path):
    for root, _, files in os.walk(directory_path):
        for file in files:
            if file.endswith('.DS_Store'):
                file_path = os.path.join(root, file)
                os.remove(file_path)

def main():
    #if len(sys.argv) < 2:
    #    print("Add a valid directory: python3 notations_analyse.py <directory_path>")
    #    sys.exit(1)

    directory_path = 'notations' #sys.argv[1]
    if os.path.isdir(directory_path):
        clean_ds_store(directory_path)
        n = explore_directory(directory_path)
        if len(n[0]) > 0 or len(n[1]) > 0:
            mix = mix_pn_dn(n[0], n[1])
            save_to_csv(mix, 'notations_analyse.csv')
            print('Thank you for using notations_analyse')
            print('Don’t hesitate to use pipotation.com !')
        else:
            print('No data could be retrieved')
    else:
        print(f"'{directory_path}' is not a valid directory")
        sys.exit(1)


if __name__ == "__main__":
    main()
