# -*- coding: iso-8859-1 -*-
from __future__ import division # 1/2 == .5 (par defaut, 1/2 == 0)
from __future__ import with_statement

##--------------------------------------##
#                  Onglets               #
##--------------------------------------##
#    WxGeometrie
#    Dynamic geometry, graph plotter, and more for french mathematic teachers.
#    Copyright (C) 2005-2007  Nicolas Pourcelot
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

#version unicode

# from LIB import *
import modules
from GUI import *
from API import *



class Onglets(wx.Notebook):
    def __init__(self, parent, id):
        style = wx.NB_TOP
        self.parent = parent
#         if wx.Platform == "__WXMAC__":
#             style = 0
        wx.Notebook.__init__(self, parent, id, style=style)


        ###############################
        ###############################
        # Creation de fonctions associees aux entrees du menu "Creer"
        import GUI.dialogues_geometrie as DG
        self.creer = {}
        dialogues = [(nom[8:], DG.__dict__[nom]) for nom in DG.__dict__.keys() if nom.startswith("Dialogue")]
        for dialogue in dialogues:
            def f(event = None, self = self, dialogue = dialogue[1]):
                self.creer_objet(dialogue)
            self.creer[dialogue[0]] = f
        del DG
        ###############################
        ###############################


        self.onglets = [] # liste des onglets

        # Ajoute les differentes composantes :
        for nom in modules.liste():
            nom = nom.lower() # le nom du module est toujours en minuscules.
            module = modules.liste(nom)
            panel = module.__panel__(self)  # ex: panel = Geometre(self)
            setattr(self, nom, panel)       #     self.geometre = panel
            menu = module.__menu__(panel)   #     menu = GeometreMenuBar(panel)
            self.nouvel_onglet(panel)


        # adaptation du titre de l'application et du menu.
        self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.changer)
        if self.onglets:
            # affiche le titre et le menu du 1er onglet
            self.actualise_onglet(self.onglets[0])
            self.onglets[0].activer()




    def nouvel_onglet(self, onglet):
        self.onglets.append(onglet)
        self.AddPage(onglet, onglet.__titre__)


    def changer(self, event):
        event.Skip()
        # onglet selectionné:
        onglet = self.onglets[event.GetSelection()]
        self.actualise_onglet(onglet)
        # Actions personnalisées lors de la sélection
        wx.CallLater(10, onglet.activer)



    def actualise_onglet(self, onglet):
        self.parent.SetMenuBar(onglet.menu) # change le menu de la fenetre
        onglet.changer_titre() # change le titre de la fenetre
        if param.plateforme == "Windows":
            if onglet.canvas is not None:
                onglet.canvas.execute_on_idle(onglet.canvas.graph.restaurer_dessin)


    def nom_onglet_actuel(self): # le nom de l'onglet actuel
        return param.modules[self.GetSelection()]


    def onglet(self, nom):
        u"nom : nom ou numéro de l'onglet."
        if type(nom) == int:
            return self.onglets[nom]
        nom = nom.lower()
        if not hasattr(self, nom):
            return
        if getattr(self, nom) in self.onglets:
            return getattr(self, nom)

##    def actuel(self): # l'onglet couramment ouvert
##        if self.onglets:
##            return self.onglets[self.GetSelection()]

    @property
    def onglet_actuel(self):
        if self.onglets:
            return self.onglets[self.GetSelection()]

    def onglet_suivant(self, event):
        self.AdvanceSelection()

    def liste_onglets(self):
        return self.onglets

    def changer_onglet(self, onglet):
        u"onglet : l'onglet proprement dit, ou son nom, ou son numéro."
        if type(onglet) in (str, unicode):
            onglet = self.onglets.index(getattr(self, nom.lower()))
        elif type(onglet) not in (int, long):
            onglet = self.onglets.index(onglet)
        self.SetSelection(onglet)




#####################################################################
#####################################################################




    def NewFile(self, event = None):
        self.onglet_actuel.creer_feuille()


    def SaveFile(self, event = None):
        actuelle = self.onglet_actuel.feuille_actuelle # feuille de travail courante
        if actuelle and actuelle.sauvegarde["nom"]:
            self.onglet_actuel.sauvegarder()
        else:
            self.SaveFileAs(event)


    def SaveFileAs(self, event = None):
        actuelle = self.onglet_actuel.feuille_actuelle # feuille de travail courante
        if actuelle and actuelle.sauvegarde["nom"]:
            fichier = actuelle.sauvegarde["nom"] # le nom par defaut est le nom précédent
            dir = actuelle.sauvegarde["repertoire"]
        else:
            fichier = ""
            if param.rep_save is None:
                dir = param.repertoire
            else:
                dir = param.rep_save

        dlg = wx.FileDialog(
            self, message = u"Enregistrer sous ...", defaultDir=dir,
            defaultFile=fichier, wildcard = u"Fichiers WxGéométrie (*.geo)|*.geo|Fichiers WxGéométrie compressés(*.geoz)|*.geoz|Tous les fichiers (*.*)|*.*", style=wx.SAVE | wx.OVERWRITE_PROMPT | wx.CHANGE_DIR
            )
        # dlg.SetFilterIndex(0)   # inutile (par defaut, la valeur est 0).

        if dlg.ShowModal() == wx.ID_OK:
            param.rep_save = os.getcwd()
            if param.rep_open is None:
                param.rep_open = param.rep_save
            if param.rep_export is None:
                param.rep_export = param.rep_save
            os.chdir(param.repertoire)
            path = dlg.GetPath()
            self.onglet_actuel.sauvegarder(path)

        dlg.Destroy()



    def OpenFile(self, event = None, detecter_module = True):
        # Attention :
        # "This dialog is set up to change the current working directory to the path chosen."
        # on enregistre donc le nouveau getcwd() - "repertoire_ouverture_fichiers = os.getcwd()", pour restaurer ensuite l'ancien
        if param.rep_open is None:
            dir = param.repertoire
        else:
            dir = param.rep_open
        dlg = wx.FileDialog(
            self, message = u"Choisissez un fichier", defaultDir=dir,
            defaultFile="", wildcard = u"Fichiers WxGéométrie (*.geo)|*.geo|Fichiers WxGéométrie compressés(*.geoz)|*.geoz|Tous les fichiers (*.*)|*.*", style=wx.OPEN | wx.MULTIPLE | wx.CHANGE_DIR
            )

        # Show the dialog and retrieve the user response. If it is the OK response,
        # process the data.
        if dlg.ShowModal() == wx.ID_OK:
            param.rep_open = os.getcwd()
            if param.rep_save is None:
                param.rep_save = param.rep_open
            if param.rep_export is None:
                param.rep_export = param.rep_open
            os.chdir(param.repertoire)
            # This returns a Python list of files that were selected.
            paths = dlg.GetPaths()
            for path in paths:
                if detecter_module: # on detecte dans quel onglet le fichier doit etre ouvert
                    self.ouvrir(path)
                else: # on l'ouvre dans l'onglet actuellement ouvert
                    self.onglet_actuel.ouvrir(path) # ouvre tous les fichiers selectionnes

        dlg.Destroy()



    def OpenFileHere(self, event = None):
        u"""Ouvrir le fichier dans le module courant.
        Par defaut, sinon, le fichier est ouvert dans le module qui l'a crée."""
        self.OpenFile(detecter_module = False)


    def ouvrir(self, path):
        u"Ouvre un fichier dans l'onglet adéquat."
        fgeo, message = ouvrir_fichierGEO(path)
        module = self.onglet(fgeo.module)
        self.parent.message(message)
        if module is not None:
            self.changer_onglet(module) # affiche cet onglet
            module.ouvrir(path) # charge le fichier dans le bon onglet
            #print_error()
        else:
            self.parent.message(u"Impossible de déterminer le module adéquat.")


    def ExportFile(self, event = None, lieu = None, sauvegarde = False):
        u"""Le paramètre sauvegarde indique qu'il faut faire une sauvegarde simultanée.
        (attention, on ne vérifie pas que le fichier .geo n'existe pas !).
        """

        formats_supportes = ('.png','.svg','.eps','.ps', '.pdf', ".bmp", ".xpm", ".jpeg", ".jpg")
        formats_natifs = formats_supportes[:5]

        actuelle = self.onglet_actuel.feuille_actuelle # feuille de travail courante
        if actuelle and actuelle.sauvegarde["export"]:
            dir, fichier = os.path.split(actuelle.sauvegarde["export"]) # on exporte sous le même nom qu'avant par défaut
        elif actuelle and actuelle.sauvegarde["nom"]:
            fichier = actuelle.sauvegarde["nom"] # le nom par defaut est le nom de sauvegarde
            dir = actuelle.sauvegarde["repertoire"]
        else:
            fichier = ""
            if param.rep_export is None:
                dir = param.repertoire
            else:
                dir = param.rep_export


        lieu = lieu or self.nom_onglet_actuel() # par defaut, le lieu est l'onglet courant

        filtre = u"PNG - Portable Network Graphic (.png)|*.png|\
EPS - Encapsulated PostScript (.eps)|*.eps|\
JPEG - Joint Photographic Experts Group (.jpg;.jpeg)|*.jpg;*.jpeg|\
SVG - Scalable Vector Graphics (.svg)|*.svg|\
PS - PostScript (.ps)|*.ps|\
BMP - Windows Bitmap (.bmp)|*.bmp|\
XPM - X PixMap (.xpm)|*.xpm|\
PDF - Portable Document Format (.pdf)|*.pdf|\
"
        extensions = [elt.split(";")[0][1:] for elt in filtre.split("|") if elt.startswith("*")] # ex: [u'.png', u'.eps', u'.jpg', u'.svg']

        dlg1 = wx.FileDialog(
                self,
                u"Exporter l'image en png, bmp, svg, ps, pdf ou eps", dir, fichier,
                filtre,
                wx.SAVE | wx.OVERWRITE_PROMPT | wx.CHANGE_DIR
                )
        if "." in fichier:
            ext = fichier.rsplit(".",1)[1]
            if ext == "jpeg":
                ext = "jpg"
            try:
                dlg1.SetFilterIndex(extensions.index("." + ext))
            except ValueError:
                debug("L'extension n'est pas dans la liste.")
        try:
            while 1:
                if dlg1.ShowModal() == wx.ID_OK:
                    param.rep_export = os.getcwd()
                    if param.rep_save is None:
                        param.rep_save = param.rep_export
                    if param.rep_open is None:
                        param.rep_open = param.rep_export
                    if sauvegarde:
                        param.rep_save = param.rep_export
                    os.chdir(param.repertoire)
                    FileName = dlg1.GetPath()
                    filename = FileName.lower()
                    # Check for proper exension
                    if True not in [filename.endswith(extension) for extension in formats_supportes]:
                        FileName += extensions[dlg1.GetFilterIndex()]
                        filename = FileName.lower()

                        #~ dlg2 = wx.MessageDialog(self, u"L'extension du fichier\n"
                        #~ u'doit être\n'
                        #~ u'png, svg, ps, jpg, bmp, xpm ou eps',
                          #~ u'Nom de fichier incorrect', wx.OK | wx.ICON_ERROR)
                        #~ try:
                            #~ dlg2.ShowModal()
                        #~ finally:
                            #~ dlg2.Destroy()
                    #~ else:
                        #~ break # now save file
                    break
                else: # exit without saving
                    return False
        finally:
            dlg1.Destroy()

        try:
            if sauvegarde:
                self.onglet(lieu).sauvegarder(mreplace(FileName, formats_supportes, ".geo"))
            # Save Bitmap
            if True in [filename.endswith(extension) for extension in formats_natifs]:
                self.onglet(lieu).exporter(FileName)
            else:
                tmp = os.tempnam() + ".png"
                f = open(tmp, "w+b")
                self.onglet(lieu).canvas.figure.savefig(tmp)
                dico = {"jpg": wx.BITMAP_TYPE_JPEG, "jpeg": wx.BITMAP_TYPE_JPEG, "bmp": wx.BITMAP_TYPE_BMP, "xpm": wx.BITMAP_TYPE_XPM}
                extension = filename.rsplit(".",1)[1]
                wx.Image(tmp, wx.BITMAP_TYPE_PNG).SaveFile(FileName, dico[extension])
                f.close()
        except:
            print_error()
            self.parent.message("Erreur lors de l'export.")

        #return self.onglet(lieu).exporter(FileName)


    def ExportAndSaveFile(self, event = None, lieu = None):
        self.ExportFile(event = event, lieu = lieu, sauvegarde = True)


    def CloseFile(self, event = None):
        self.onglet_actuel.fermer_feuille()


    def PageSetup(self, event = None):
        self.a_venir()

    def Printout(self, event = None):
        self.a_venir()

    def a_venir(self, event = None):
        dlg = wx.MessageDialog(self, u"Fonctionnalité non présente pour l'instant !", u"A venir !", wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()



    def CloseWindow(self, event):
        self.parent.Close(True)





    def supprimer(self, event = None):
        canvas = self.onglet_actuel.canvas
        dlg = SupprimerObjet(self)
        if (dlg.ShowModal() == wx.ID_OK):
            with canvas.geler_affichage(actualiser = True):
                for selection in dlg.GetValueString():
                    try:
                        # Il est normal que des erreurs soient renvoyées
                        # si un objet dépendant d'un autre est déjà supprimé.
                        objet = selection.split()[1]
                        canvas.executer("del " + objet)
                    except Exception:
                        print_error()
        dlg.Destroy()


    def editer(self, event = None):
        from GUI.proprietes_objets import Proprietes # à deplacer !!
        feuille = self.onglet_actuel.feuille_actuelle
        if feuille:
            objets = []
            dlg = EditerObjet(self)
            val = dlg.ShowModal()
            if val == wx.ID_OK:
                objets = [feuille.objets[selection.split()[1]] for selection in dlg.GetValueString()]
            dlg.Destroy()

            if objets:
                win = Proprietes(self, objets)
                win.Show(True)
                def fermeture(event, win = win):
                    win.Unbind(wx.EVT_CLOSE)
                    win.Close()
                    self.editer()
                win.Bind(wx.EVT_CLOSE, fermeture)
        #self.parent.Raise()


    def creer_objet(self, classe):
        dl = classe(self)
        # this does not return until the dialog is closed.
        while 1:
            canvas = self.onglet_actuel.canvas
            resultat = dl.affiche()
            if resultat == wx.ID_OK:
                try:
                    canvas.executer(dl.commande(), parser = True)
                    break
                except NameError:
                    print_error()
                    canvas.message(u'Erreur : nom déjà utilisé ou nom réservé.')
                except:
                    print_error()
                    canvas.message(u'Erreur : paramètres incorrects.')
            else:
                break
        dl.Destroy()


    def Securite(self, securite = None):
        u"Passer en mode sécurisé."
        if securite is not None:
            if isinstance(securite, bool):
                param.securite = securite
            else:
                param.securite = not param.securite
        return param.securite

        #if param.securite:  self.parent.b.Disable()
        #else:  self.parent.b.Enable()


    def LigneCommande(self, afficher = None):
        u"Afficher ou non la ligne de commande."
        if afficher is not None:
            if isinstance(afficher, bool):
                param.ligne_commande = afficher
            else:
                param.ligne_commande = not param.ligne_commande
            self.parent.tb.Show(param.ligne_commande)
            self.parent.SendSizeEvent()
        return param.ligne_commande


    def Debug(self, debug = None):
        u"Passer en mode déboguage."
        if debug is not None:
            if isinstance(debug, bool):
                param.debug = debug
            else:
                param.debug = not param.debug
            app = self.parent.application
            if param.debug:
                app.RedirectStdio(None)     # redirection vers une fenetre de messages
            else:
                app.RestoreStdio()
                if app.stdioWin:
                    app.stdioWin.close()
        return param.debug

    def Animer(self, event):
        from GUI.animer import DialogueAnimation
        d = DialogueAnimation(self)
        d.CenterOnParent(wx.BOTH)
        d.Show(True)

    def Histo(self, event):
        h = FenCode(self)
        h.SetSize((400, 500))
        h.CenterOnParent(wx.BOTH)
        h.Show(True)


    def Proprietes(self, event):
        from GUI.proprietes_feuille import ProprietesFeuille # à deplacer ?
        actuelle = self.onglet_actuel.feuille_actuelle # feuille courante
        win = ProprietesFeuille(self, actuelle)
        win.Show(True)


    def Aide(self, event):
        aide = Help(self, path2("%/doc/help.htm"))
        aide.Show(True)

    def Verifier_version(self, event):
        from GUI.nouvelles_versions import verifier_version # à deplacer ?
        verifier_version(self)

    def Notes(self, event):
        f = open(path2("%/doc/notes.txt"), "r")
        msg = f.read().decode("utf8")
        f.close()
        msg = msg.replace(u"WxGeometrie", u"WxGéométrie version " + param.version, 1)
        dlg = wx.lib.dialogs.ScrolledMessageDialog(self, msg, "Notes de version")
        dlg.ShowModal()

    def Licence(self, event):
        f = open(path2("%/doc/license.txt"), "r")
        msg = f.read().decode("utf8")
        f.close()
        msg = msg.replace(u"WxGeometrie", u"WxGéométrie version " + param.version, 1)
        dlg = wx.lib.dialogs.ScrolledMessageDialog(self, msg, "Licence")
        dlg.ShowModal()

    def Contacter(self, event):
        from GUI.contact import Contact
        dialog = Contact(self)
        val = dialog.ShowModal()
        if val == wx.ID_OK:
            dialog.rapporter()
        dialog.Destroy()


    def About(self, event):
        dialog = About(self)
        btn = dialog.ShowModal()
        dialog.Destroy()

    def Informations(self, event):
        dialog = Informations(self)
        btn = dialog.ShowModal()
        dialog.Destroy()
