'''
BlueCrocodile production 2021

Retrieve cable list from JSON files
controls:
    - no duplicates are present
    - every cable in JSON has a correspondance into SVG  (cables in SVG are in the lines strating as "<g id=" )

reports:
    - analysed directories
    - errors found

allows:
    - addressing a root directory containing all the directories to be analysed (one level only)
    - writing a log file
'''


import tkinter as tk
from tkinter import filedialog
import os.path
from os.path import isfile

# -- modules --
import loadfiles_data as lfd
import appicon



# class dir - the construcors fills the list of subdirs and list of files
class dir:

    def __dirimport(self, dname :str):
        try:
            subdirs = [os.path.join(dname, d) for d in os.scandir(dname) if d.is_dir()] #list of one-levvel subdirectories
        except:
            print(" ERRORE: impossibile aprire la cartella " + dname + '\n')  
        else:
            return subdirs

    def __fileload(self, dname :str):
        try:
            filenames = [os.path.join(dname, f) for f in os.listdir(dname) if isfile(os.path.join(dname, f))] #list of files in the directory  
        except:
            print(" ERRORE: impossibile aprire la cartella " + dname + '\n\n')  
        else:
            return filenames


    def __init__(self, dirname :str):
        self.dirname = dirname
        self.__subdirs = self.__dirimport(dirname)
        self.__ownfiles = self.__fileload(dirname)

    def name(self):
        return self.dirname
    
    def subdirs(self):
        return self.__subdirs

    def ownfiles(self):
        return self.__ownfiles


# append a message in text box
def printappend(s):   #append message s in the pad area
    msg.insert(tk.END, s + "\n") 
    msg.see(tk.END)


# opens the dialog for choosing the root directory
# returns root_dir path
def dir_open():

    root_dir = tk.filedialog.askdirectory(title='Apri cartella dei file da analizzare')
    if len(root_dir) == 0:
        return None
    #root_dname = os.path.basename(root_dir)
    printappend("AVVIO ANALISI: cartella " + root_dir + " e sue sottocartelle\n") 
    return root_dir    


# verifies correctness of the dir object:
#  - there is 1 file svg and 1 file json, but accepts 0 files only if there are subdirectories
# returns dir is ok (bool) and the 2 files (svg and json) if present
def dircontrol(d :dir):

    numdir = len(d.subdirs())
    list_svg = [f for f in d.ownfiles() if (f.endswith(".svg") or f.endswith(".SVG"))]
    list_jsn = [f for f in d.ownfiles() if (f.endswith(".json") or f.endswith(".JSON"))]
    numsvg = len(list_svg)
    numjsn = len(list_jsn)
    if numdir > 0:
        if (((numsvg > 1) or (numjsn > 1)) or (numsvg != numjsn)):
            printappend("  - ERRORE:  Troppi file nella directory " + d.name() +"\n")
            return False, None, None
    else:
        if (numsvg != 1) or (numjsn !=1):
            printappend("  - ERRORE:  numero file non congruente nella directory " + d.name() +"\n")
            return False, None, None

    # the directory is valid - returning also the svg and jsn file if there are
    if len(list_svg) == 1:        
        return True, list_svg[0], list_jsn[0]
    else:
        return True, None, None


# verifies that cables in the json are referenced in the svg file, otherwise append an error message
def compare(svgfile, jsnfile :str):
    jsn_data, jsn_dup = lfd.loadjson_data(jsnfile)
    if jsn_dup is not None:
        [printappend(f' - ATTENZIONE cablaggio {c} duplicato nel file {jsnfile}\n') for c in jsn_dup]
    svg_data = lfd.loadsvg_data(svgfile)
    for item in jsn_data:
       if item not in svg_data:
           printappend(f"  - ERRORE in {jsnfile}: cablaggio {item} senza riferimento\n")


# verifies if the current dir has svg and json files and launches the comparation
def verify(workingdir :dir):
    printappend(f" >> Verifica dei file nella cartella {workingdir.dirname} \n")
    dfiles = workingdir.ownfiles()
    # verify if the directory is ok
    tup = dircontrol(workingdir)  # acquires the returns of the dircontrol function
    if tup[0] and tup[1] != None: # if the dir is ok and there are svg (and json) files
        compare(tup[1], tup[2])   # execute the control in the workingdirectory
    else: printappend("  - la directory " + workingdir.dirname + " viene ignorata \n")   


# do the intere work
def main_work():
    root_dir = dir_open()
    if len(root_dir) == 0:
        return
    
    # before verifies files in the root
    root = dir(root_dir)
    verify(root)

    # then verifies files in each subdirectory of the root
    for d in root.subdirs():
        workingdir = dir(d)
        verify(workingdir)
        del workingdir
    
    printappend(" - CONTROLLO TERMINATO\n")
    btn3['state']='normal'


# Save the content of the textbox in a log file
def logexport():

    log = tk.filedialog.asksaveasfilename(title='Inserisci il nome del log', defaultextension='.log', filetypes=[("log files", '*.log')])
    if len(log) == 0:
        return None
    with open(log, mode='w') as filelog:
        # writing time
        from datetime import datetime
        now = datetime.now()
        filelog.write(now.strftime("%d/%m/%Y %H:%M:%S "))
        # writing msg
        filelog.write(msg. get("1.0","end"))

    printappend("- Log salvato " + log + "\n") 
    return



# --------- MAIN -------------------
rootwin=tk.Tk()
rootwin.title('Acquisizione lista cablaggi da SVG - ver. 0.1')
rootwin.geometry('520x510')

# windows icon (the blue crocodile)
tempfilename = "icon.ico"
appicon.create_iconfile(tempfilename)
# TODO verify the problem with the following
#rootwin.wm_iconbitmap(tempfilename)
os.remove(tempfilename) # deleting tempfile

msg=tk.Text(rootwin, padx=3, pady=3, relief='groove', bg='white', width=55, heigh=21)
#msg.pack(fill='both')
msg.grid(row=1, column=0, columnspan=3, sticky=tk.NS)

scrollbar = tk.Scrollbar(rootwin)
scrollbar.grid(row=1, columnspan=3, sticky="NSE")
msg.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=msg.yview)

btn1=tk.Button(rootwin, text='Seleziona la cartella da analizzare', command=main_work, padx=2, pady=3)
btn1.grid(row=0, column=0, padx=20, pady=20)

btn3=tk.Button(rootwin, text='Esporta Log file', command=logexport, padx=2, pady=3, state='disabled')
btn3.grid(row=0, column=2, padx=20, pady=20, ipadx=6)

btn_exit=tk.Button(rootwin, text='Esci', command=rootwin.quit, padx=2, pady=3)
btn_exit.grid(row=2, column=2, padx=20, pady=10, ipadx=15)

cpr=tk.Label(rootwin, padx=1, text="BlueCrocodile production © 2021", fg='gray', font=('verdana',7))
cpr.grid(row=3, columnspan=3, sticky="SE")

rootwin.mainloop()
