from AppliDef import *
from SerialMonitor import *
import subprocess
import time


def Televersement(Port, CheminArduinoProg, CheminINO):
    arduinoCommand = '"' + CheminArduinoProg + '/arduino" --upload ' + " --board arduino:avr:uno" + " --port " \
                     + Port + " " + CheminINO
    presult = subprocess.call(arduinoCommand, shell=True)
    time.sleep(5)
    if presult != 0:
        tkMB.showwarning('Attention', "Echec du téléversement!")
    else:
        tkMB.showinfo('Arduino', 'Fin du téléversement')


def ExtractNameFile(PathFile):
    FileIno = ''
    for i in range(len(PathFile), 0, -1):
        if PathFile[i - 1:i] != '/':
            FileIno = FileIno + PathFile[i - 1:i]
        else:
            break
    FileIno2 = ''
    for i in range(len(FileIno), 0, -1):
        FileIno2 = FileIno2 + FileIno[i - 1:i]
    return FileIno2


class FrmSketchIDE(tk.Toplevel):
    def __init__(self, container, RatioX, RatioY, RatioY2, IndexFile, Appli):
        tk.Toplevel.__init__(self, container)
        self.MainAppli = Appli
        self.parent = container
        self.RatioX = RatioX
        self.RatioY = RatioY
        self.RatioY2 = RatioY2
        self.IndexFile = IndexFile

        self.ListCanvasBtn = []
        self.ListBtn = []
        self.ListImgBtn = []
        self.ListInfoAction = ['Vérifier', 'Téléverser', 'Nouveau', 'Ouvrir', 'Enregistrer']
        self.InfoAction = False
        self.TooltipAction = None
        self.ModifTextINO = False
        self.FileSaved = False
        self.BtnFermerVisible = False
        self.ComptSketch = 0
        self.PathFileInoToOpen = ''
        self.PathFileInoToSave = ''
        self.CheminINO = ''
        self.AffichRapportCompil = False
        self.FrmSerialMonitor = None

        screen = ctypes.windll.user32
        FrmFond = Image.open('Media/FrmINO/Fond/Fond.jpg')
        self.SX = int((float(FrmFond.size[0]) * float(self.RatioX)))
        self.SY = int((float(FrmFond.size[1]) * float(self.RatioY)))

        self.ImgFrmFond = []
        self.ImgFrmFond = RedimImg(self.SX, self.SY, 'Media/FrmINO/Fond/')
        self.CanvasFrmFond = CanvasApp(self, width=self.SX, height=self.SY)
        self.ImgCanvasFrmFond = self.CanvasFrmFond.create_image(0, 0, anchor=tk.NW, image=self.ImgFrmFond[0])

        self.geometry(str(self.SX) + "x" + str(self.SY) + "+" + str(int(screen.GetSystemMetrics(0) * 0.174)) + "+" +
                      str(int(screen.GetSystemMetrics(1) * 0.080)))
        self.resizable(width=False, height=False)
        self.overrideredirect(True)
        self.lift(container)

        self.Verifier, wsize, hsize, self.CanvasVerifier, self.ImgVerifier = CanInWindow(
            'Media/FrmINO/BtnVerifier/', self.RatioX, self.RatioY2, self.CanvasFrmFond,
            int(self.SX * 0.02), int(self.SY * 0.024), 0)
        self.ListCanvasBtn.append(self.CanvasVerifier)
        self.ListBtn.append(self.Verifier)
        self.ListImgBtn.append(self.ImgVerifier)

        self.Televerser, wsize, hsize, self.CanvasTeleverser, self.ImgTeleverser = CanInWindow(
            'Media/FrmINO/BtnTeleverser/', self.RatioX, self.RatioY2, self.CanvasFrmFond,
            int(self.SX * 0.05), int(self.SY * 0.024), 0)
        self.ListCanvasBtn.append(self.CanvasTeleverser)
        self.ListBtn.append(self.Televerser)
        self.ListImgBtn.append(self.ImgTeleverser)

        self.Nouveau, wsize, hsize, self.CanvasNouveau, self.ImgNouveau = CanInWindow(
            'Media/FrmINO/BtnNouveau/', self.RatioX, self.RatioY2, self.CanvasFrmFond,
            int(self.SX * 0.08), int(self.SY * 0.024), 0)
        self.ListCanvasBtn.append(self.CanvasNouveau)
        self.ListBtn.append(self.Nouveau)
        self.ListImgBtn.append(self.Nouveau)

        self.Ouvrir, wsize, hsize, self.CanvasOuvrir, self.ImgOuvrir = CanInWindow(
            'Media/FrmINO/BtnOuvrir/', self.RatioX, self.RatioY2, self.CanvasFrmFond,
            int(self.SX * 0.105), int(self.SY * 0.024), 0)
        self.ListCanvasBtn.append(self.CanvasOuvrir)
        self.ListBtn.append(self.Ouvrir)
        self.ListImgBtn.append(self.ImgOuvrir)

        self.Enregistrer, wsize, hsize, self.CanvasEnregistrer, self.ImgEnregistrer = CanInWindow(
            'Media/FrmINO/BtnEnregistrer/', self.RatioX, self.RatioY2, self.CanvasFrmFond,
            int(self.SX * 0.13), int(self.SY * 0.024), 0)
        self.ListCanvasBtn.append(self.CanvasEnregistrer)
        self.ListBtn.append(self.Enregistrer)
        self.ListImgBtn.append(self.Enregistrer)

        for i in range(len(self.ListCanvasBtn)):
            ChangeCursor(self.ListCanvasBtn[i])

            def GestEvt(_, j=i):
                return self.ActionBtn(j)

            def GestEvt2(_, j=i):
                return self.MotionBtn(j)

            self.ListCanvasBtn[i].bind('<Button-1>', GestEvt)
            self.ListCanvasBtn[i].bind('<Motion>', GestEvt2)

        self.MoniteurSerie, wsize, hsize, self.CanvasMoniteurSerie, self.ImgMoniteurSerie = CanInWindow(
            'Media/FrmINO/BtnMoniteurSerie/', self.RatioX, self.RatioY2, self.CanvasFrmFond,
            int(self.SX * 0.98), int(self.SY * 0.024), 0)
        ChangeCursor(self.CanvasMoniteurSerie)
        self.CanvasMoniteurSerie.bind('<Button-1>', self.ActionMoniteurSerie)
        self.CanvasMoniteurSerie.bind('<Motion>', self.MotionMoniteurSerie)

        ZDTWidth = int(self.SX * float(ConfigResolution(self.MainAppli.Nconfig, 'SI1')))

        ZDTHeight = int(self.SY * float(ConfigResolution(self.MainAppli.Nconfig, 'SI2')))

        self.ZoneTextINO = ZoneScrolledText(self.CanvasFrmFond, width=ZDTWidth, height=ZDTHeight,
                                            font=FontText2(12))
        self.CanvasFrmFond.create_window(int(self.SX * 0.007), int(self.SY * 0.083), anchor=tk.NW,
                                         window=self.ZoneTextINO)

        if self.IndexFile >= 0:
            self.NameFileINO = self.MainAppli.ListTitreSketchs[self.IndexFile]
            if self.MainAppli.ListSketchs[self.IndexFile][4] is not None:
                self.CheminINO = self.MainAppli.ListSketchs[self.IndexFile][4]
                self.AffichFileInZoneTxt(self.CheminINO)
                self.FileSaved = True
                self.PathFileInoToSave = self.CheminINO
        else:
            self.ComptSketch = self.ComptSketch + 1
            self.NameFileINO = 'Sketch' + str(self.ComptSketch)

        self.LabelNameFileINO = LabelText(self.CanvasFrmFond, self.NameFileINO, 'white', font=FontLabel2(10))
        self.CanvasFrmFond.create_window(int(self.SX * 0.01), int(self.SY * 0.052), anchor=tk.NW,
                                         window=self.LabelNameFileINO)

        self.Fermer, wsize, hsize, self.CanvasFermer, self.ImgFermer = CanInWindow(
            'Media/FrmINO/BtnFermer/', self.RatioX, self.RatioY2, self.CanvasFrmFond,
            int(self.SX * 0.98), int(self.SY * 0.06), 2)
        self.CanvasFermer.bind('<Button-1>', self.ActionFermer)
        self.CanvasFermer.bind('<Motion>', self.MotionFermer)

        self.CanvasFrmFond.bind('<Motion>', self.MotionCanvasFrmFond)
        self.CanvasFrmFond.pack()

    def ActionBtn(self, i):
        if i == 0:
            self.ActionVerifier()
        elif i == 1:
            self.ActionTeleverser()
        elif i == 2:
            self.ActionNouveau()
        elif i == 3:
            self.ActionOuvrir()
        elif i == 4:
            self.ActionEnregistrer()

    def MotionBtn(self, i):
        self.ListCanvasBtn[i].itemconfig(self.ListImgBtn[i], image=self.ListBtn[i][1])
        self.AffichInfoAction(self.ListInfoAction[i])

    def AffichInfoAction(self, Action):
        if self.InfoAction:
            self.CanvasFrmFond.delete(self.TooltipAction)
            self.InfoAction = False
        if Action == 'Moniteur Série':
            Rx = 0.85
        else:
            Rx = 0.15
        self.TooltipAction = self.CanvasFrmFond.create_text(int(self.SX * Rx),
                                                            int(self.SY * 0.018), anchor=tk.NW, text=Action,
                                                            fill='white', font=FontLabel2(10))
        self.InfoAction = True

    def EffaceInfoAction(self):
        for i in range(len(self.ListCanvasBtn)):
            self.ListCanvasBtn[i].itemconfig(self.ListImgBtn[i], image=self.ListBtn[i][0])
        self.CanvasMoniteurSerie.itemconfig(self.ImgMoniteurSerie, image=self.MoniteurSerie[0])
        if self.InfoAction:
            self.CanvasFrmFond.delete(self.TooltipAction)
            self.InfoAction = False

    def ActionMoniteurSerie(self, _):
        self.EffaceInfoAction()
        self.ChargeSerialMoniteur()

    def ChargeSerialMoniteur(self):
        self.FrmSerialMonitor = FrmSerialMonitor(self.MainAppli.parent, int(self.SX),
                                                 int(self.SY), self)
        self.MainAppli.SerialMonitor = True

    def MotionMoniteurSerie(self, _):
        self.CanvasMoniteurSerie.itemconfig(self.ImgMoniteurSerie, image=self.MoniteurSerie[1])
        self.AffichInfoAction('Moniteur Série')

    def MotionCanvasFrmFond(self, _):
        self.EffaceInfoAction()
        if self.BtnFermerVisible:
            self.CanvasFermer.itemconfig(self.ImgFermer, image=self.Fermer[0])

    def AffichFileInZoneTxt(self, PathFile):
        self.ZoneTextINO.delete(0.0, tk.END)
        Fichier = open(PathFile, "r", encoding="utf-8")
        for line in Fichier:
            self.ZoneTextINO.insert(tk.INSERT, line)
        Fichier.close()
        self.ZoneTextINO.tag_add('ZoneTextINOTag', 0.0, tk.END)
        self.ZoneTextINO.tag_bind('ZoneTextINOTag', '<KeyPress>', self.ActionModifTextINO)

    def ActionModifTextINO(self, _):
        self.ModifTextINO = True
        self.LabelNameFileINO.config(text='*' + self.NameFileINO)

    def ActionVerifier(self):
        self.EffaceInfoAction()
        self.BuildSketch(self.MainAppli.CheminArduinoProg, self.CheminINO)

    def ActionTeleverser(self):
        self.EffaceInfoAction()
        if self.MainAppli.ModeControlArduino:
            if self.MainAppli.ArduinoPort != '':
                if self.ModifTextINO:
                    Rep = tkMB.askyesno(self.NameFileINO, "Le fichier a été modifié. Il doit être enregistré avant "
                                                          "le téléversement. Souhaitez-vous l'enregistrer ?")
                    if Rep:
                        self.ActionEnregistrer()
                        if not self.ModifTextINO:
                            self.MainAppli.parent.lift()
                            Televersement(self.MainAppli.ArduinoPort, self.MainAppli.CheminArduinoProg, self.CheminINO)
                else:
                    self.MainAppli.parent.lift()
                    Televersement(self.MainAppli.ArduinoPort, self.MainAppli.CheminArduinoProg, self.CheminINO)
            else:
                tkMB.showwarning('Attention', "Le port COM de l'Arduino n'est pas configuré !")
        else:
            tkMB.showwarning('Attention', "Aucun Arduino UNO n'a été détecté !")
        self.lift(self.parent)

    def ActionNouveau(self):
        self.EffaceInfoAction()
        self.FileSaved = False
        self.PathFileInoToSave = ''
        self.ModifTextINO = True
        self.ComptSketch = self.ComptSketch + 1
        self.ZoneTextINO.delete(0.0, tk.END)
        self.NameFileINO = 'Sketch' + str(self.ComptSketch)
        self.LabelNameFileINO.config(text=self.NameFileINO)
        if self.ComptSketch > 1 or self.IndexFile >= 0:
            self.AffichBtnFermer()
        self.InitSelection()

    def ActionOuvrir(self):
        self.EffaceInfoAction()
        self.PathFileInoToOpen = ''
        self.PathFileInoToOpen = tkfiledialog.askopenfilename(title="Ouvrir un fichier",
                                                              initialdir="Sketchs/Saves/Codes",
                                                              filetypes=[('INO files', '.ino')])
        if self.PathFileInoToOpen != '':
            self.AffichFileInZoneTxt(self.PathFileInoToOpen)
            self.CheminINO = self.PathFileInoToOpen
            self.FileSaved = True
            self.NameFileINO = ExtractNameFile(self.PathFileInoToOpen)
            self.NameFileINO = self.NameFileINO[0:len(self.NameFileINO) - 4]
            self.LabelNameFileINO.config(text=self.NameFileINO)
            self.PathFileInoToSave = self.PathFileInoToOpen
            self.AffichBtnFermer()
        self.InitSelection()
        self.lift(self.parent)

    def ActionEnregistrer(self):
        self.EffaceInfoAction()
        if not self.FileSaved:
            self.PathFileInoToSave = ''
            self.PathFileInoToSave = tkfiledialog.asksaveasfilename(title="Enregistrer sous",
                                                                    filetypes=[('INO files', '.ino')],
                                                                    initialdir="Sketchs/Saves/Codes",
                                                                    defaultextension='.ino')
            if self.PathFileInoToSave != '':
                PathDirInoToSave = self.PathFileInoToSave[0:len(self.PathFileInoToSave) - 4] + '/'
                self.NameFileINO = ExtractNameFile(self.PathFileInoToSave)
                self.PathFileInoToSave = PathDirInoToSave + self.NameFileINO
                os.makedirs(PathDirInoToSave, exist_ok=True)
                FileInoToSave = open(self.PathFileInoToSave, "w", encoding="utf-8", )
                InoToSave = self.ZoneTextINO.get(0.0, tk.END)
                FileInoToSave.write(InoToSave)
                FileInoToSave.close()
                self.FileSaved = True
                self.CheminINO = self.PathFileInoToSave
                self.NameFileINO = self.NameFileINO[0:len(self.NameFileINO) - 4]
                self.LabelNameFileINO.config(text=self.NameFileINO)
                self.AffichBtnFermer()
                self.ModifTextINO = False
                self.ZoneTextINO.tag_add('ZoneTextINOTag', 0.0, tk.END)
                self.ZoneTextINO.tag_bind('ZoneTextINOTag', '<KeyPress>', self.ActionModifTextINO)
        else:
            FileInoToSave = open(self.PathFileInoToSave, "w", encoding="utf-8", )
            InoToSave = self.ZoneTextINO.get(0.0, tk.END)
            FileInoToSave.write(InoToSave)
            FileInoToSave.close()
            self.ModifTextINO = False
            self.LabelNameFileINO.config(text=self.NameFileINO)
            self.ZoneTextINO.tag_add('ZoneTextINOTag', 0.0, tk.END)
            self.ZoneTextINO.tag_bind('ZoneTextINOTag', '<KeyPress>', self.ActionModifTextINO)
        self.lift(self.parent)

    def ActionFermer(self, _):
        if self.IndexFile >= 0:
            self.NameFileINO = self.MainAppli.ListTitreSketchs[self.IndexFile]
            self.LabelNameFileINO.config(text=self.NameFileINO)
            if self.MainAppli.ListSketchs[self.IndexFile][4] is not None:
                self.AffichFileInZoneTxt(self.MainAppli.ListSketchs[self.IndexFile][4])
            else:
                self.ZoneTextINO.delete(0.0, tk.END)
            self.MainAppli.ListBoxFichiers.selection_set(self.IndexFile)
            self.MainAppli.AffichSketch(self.IndexFile)
        else:
            self.ComptSketch = 1
            self.NameFileINO = 'Sketch' + str(self.ComptSketch)
            self.LabelNameFileINO.config(text=self.NameFileINO)
            self.ZoneTextINO.delete(0.0, tk.END)
        self.FileSaved = False
        self.CacheBtnFermer()

    def MotionFermer(self, _):
        if self.BtnFermerVisible:
            self.CanvasFermer.itemconfig(self.ImgFermer, image=self.Fermer[1])

    def AffichBtnFermer(self):
        self.CanvasFermer.itemconfig(self.ImgFermer, image=self.Fermer[0])
        ChangeCursor(self.CanvasFermer)
        self.BtnFermerVisible = True

    def CacheBtnFermer(self):
        self.CanvasFermer.itemconfig(self.ImgFermer, image=self.Fermer[2])
        self.BtnFermerVisible = False
        ChangeCursor2(self.CanvasFermer)

    def InitSelection(self):
        self.MainAppli.ListBoxFichiers.selection_clear(0, tk.END)
        self.MainAppli.LabelTitre.config(text='')
        self.MainAppli.CanvasImgCircuit.itemconfig(self.MainAppli.ImgCanvasImgCircuit,
                                                   image=self.MainAppli.ImgCircuit[
                                                       len(self.MainAppli.ListCircuitSketchs)])
        self.MainAppli.InitOnglets2()

    def BuildSketch(self, CheminArduinoProg, CheminINO):
        arduinoCommand = '"' + CheminArduinoProg + '/arduino" --verify ' + " " + CheminINO

        with open('Sketchs/BuildSketch/out.txt', 'w+') as FileOut:
            with open('Sketchs/BuildSketch/err.txt', 'w+') as FileErr:
                subprocess.call(arduinoCommand, shell=True, stdout=FileOut, stderr=FileErr)

        Rep = tkMB.askyesno(self.NameFileINO + ' - Compilation', "Souhaitez-vous voir le rapport de compilation ?")
        if Rep:
            self.ZoneTextINO.delete(0.0, tk.END)
            self.LabelNameFileINO.config(text=self.NameFileINO + ' - Rapport de compilation')
            File = open('Sketchs/BuildSketch/err.txt', "r")
            for line in File:
                self.ZoneTextINO.insert(tk.INSERT, line)
            File = open('Sketchs/BuildSketch/out.txt', "r")
            for line in File:
                self.ZoneTextINO.insert(tk.INSERT, line)
            self.AffichRapportCompil = True
            self.AffichBtnFermer()
        self.lift(self.parent)
