import wxversion
wxversion.select('2.6')
import wx
#import  wx.lib.filebrowsebutton2 as filebrowse
import  wx.lib.scrolledpanel as scrolled
import wx.stc as stc
import webbrowser

from gallery_param import *
import main_gallery
import gallery_cmd
import dirbrowse2
from setter import createBindIntSetter, createBindRadioSetter 

import os.path
import sys

##ID_ABOUT=101
##ID_SAVE=103

class HelpFrame(wx.Frame):
    def __init__(self, parent, title, mainFrame):

        wx.Frame.__init__(self, parent, -1, title)
        self.mainFrame = mainFrame
        panel = wx.Panel(self)
        control = wx.TextCtrl(panel, -1, 
                            style=wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH)
        style = control.GetDefaultStyle()
        font = style.GetFont() 
        font.SetFamily(wx.FONTFAMILY_MODERN) 
        style.SetFont(font)
        control.SetDefaultStyle(style)
        control.WriteText(gallery_cmd.intro())
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(control, 1, wx.EXPAND | wx.ALL, 0)             
        panel.SetSizer(sizer)
        panel.Layout()
        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)


    def OnCloseWindow(self, event):
        self.mainFrame.helpWin = None
        self.Destroy()

        
#=========================================================

class MyFrame(wx.Frame):
    """
    Manage files and gallery creation.
    """
    def __init__(self, parent, title, args, param):
        wx.Frame.__init__(self, parent, -1, title,
                          pos=(0, 0), size=(450, 700))
        # at present one or more args may be given from the commandline
        # none will appear in the file browser, but the first should have
        #   its picdocs displayed if they exist.
        # Through the commandline is the only way presently to supply more than
        #   one source directory.
        self.args = args
        self.param = param
##        self.setMenus()
        self.CreateStatusBar()
 
        def print_status(s, frame = self): 
           frame.SetStatusText(s)
        
        self.param.display = print_status
        self.SetStatusText("Welcome to the Gallery!")      

        # Now create the Panel to put the other controls on.
        self.makePanel()
        
        self.setText()
        
##    def setMenus(self):
##        filemenu = wx.Menu()
##        filemenu.Append(ID_ABOUT, "&About"," Information about this program")
####        filemenu.Append(ID_SAVE,"&Save"," Save the current file")
##        filemenu.AppendSeparator()
##        filemenu.Append(wx.ID_EXIT, "E&xit\tAlt-X", "Exit the program.")
##
##        self.Bind(wx.EVT_MENU, self.OnAbout, id=ID_ABOUT) 
####        self.Bind(wx.EVT_MENU, self.onSave, id=ID_SAVE)
##        self.Bind(wx.EVT_MENU, self.OnTimeToClose, id=wx.ID_EXIT)
##
##        menuBar = wx.MenuBar()
##        menuBar.Append(filemenu, "&File")
##        self.SetMenuBar(menuBar)
           
    def makePanel(self):      
        self.panel = wx.Panel(self)

        self.dbb = dirbrowse2.DirBrowseButton2(
            self.panel, -1, changeCallback = self.dbbCallback,
            labelText = "Choose Source Folder",
            startDirectory = os.path.abspath("."))

        self.grid = self.makeGrid(self.panel)
        self.showParams = True;
        self.toggleButton = \
                self.doButton(wx.Button(self.panel, -1, "Hide Parameters"),
                              self.toggleShowParams)
        self.saveButton = self.doButton(wx.Button(self.panel, -1, "Save text"),
                                                  self.onSave)
        self.saveButton.Enable(False)
##        self.control = wx.TextCtrl(self.panel, -1, style=wx.TE_MULTILINE)
        self.control = stc.StyledTextCtrl(self.panel, -1)
##        SetReadOnly(bool readOnly)
        self.control.SetWrapMode(True)
##        
##        
##        
        sizer = wx.BoxSizer(wx.VERTICAL)
        
        sizer.Add(self.dbb, 0, wx.EXPAND | wx.ALL, 5)
        sizer.Add(self.grid, 0, wx.ALL, 5)
        
        buttonsizer = wx.BoxSizer(wx.HORIZONTAL)
        buttonsizer.Add(self.doButton(wx.Button(self.panel, -1, "Make Gallery"),
                                      self.go, 
                                      "After the parameters are right,\n"+
                                      " (re)make the gallery."),
                        0, wx.ALL, 5)
        buttonsizer.Add(self.toggleButton, 0, wx.ALL, 5)
        buttonsizer.Add(self.doButton(self.saveButton, self.onSave),
                        0, wx.ALL, 5)
        self.helpWin = None
        buttonsizer.Add(self.doButton(wx.Button(self.panel, -1, "Help"), 
                                      self.OnHelpButton),
                        0, wx.ALL, 5)
        sizer.Add(buttonsizer, 0, wx.EXPAND | wx.ALL, 5)
        sizer.Add(self.control, 1, wx.EXPAND | wx.ALL, 5)
        
        self.panel.SetSizer(sizer)
        self.panel.Layout()

    def doButton(self, button, cmd, tooltip = ""):
        if tooltip: 
            button.SetToolTipString(tooltip)
        self.Bind(wx.EVT_BUTTON, cmd, button)
        return button
    
    def toggleShowParams(self, e):
        self.showParams = not self.showParams
        self.panel.GetSizer().Show(self.grid, self.showParams, True)
        if self.showParams:
            value =  "Hide Parameters"
        else:
            value =  "Show Parameters"
        self.toggleButton.SetLabel(value)
        self.grid.Layout()
        self.panel.Layout()
        

    def OnHelpButton(self, evt):
        if self.helpWin:
            if self.helpWin.IsIconized(): # need to skip if not windows?
                self.helpWin.Maximize(False)
            self.helpWin.Raise()
        else:    
            self.helpWin = HelpFrame(self, "Help", self)
            self.helpWin.SetSize((580, 600))
##          self.helpWin.CenterOnParent(wx.BOTH)
            self.helpWin.Show(True)

##    def OnAbout(self,e):
##        d= wx.MessageDialog( self, "A simple image gallery program \n"
##                            " by Andrew Harrington\n"
##                            "run\n"
##                            "  python make_gallery -h\n"
##                            "for help with command line options.",
##                            "About the Gallery", wx.OK)  
##        d= wx.MessageDialog( self, gallery_cmd.intro(), wx.OK)  
##        d.ShowModal() 
##        d.Destroy() 
        
        
    def onSave(self,e):
        """ Save the current file """
        if not self.saveButton.IsEnabled():
            return
##        currText = self.control.GetValue();
        currText = self.control.GetText();
        if currText != self.origText:
            try:
                f=open(self.getFileName(),"w")
                f.write(currText)
                f.close()
                self.origText = currText
                self.SetStatusText("Text Saved To %s." % self.getFileName())
            except:
                popError(self,"Error writing file %s!" % self.getFileName())
        else:
            self.SetStatusText("No change in text in %s." % self.getFileName())      
            

        
    def setText(self):
        """ Open Pic docs in text control"""
        disable = True
        if self.getFileName():
            try:
                f=open(self.getFileName(),'r')
                s = f.read()
                f.close()
                self.origText = s;
                self.saveButton.Enable()
                disable = False
            except:
                s = "    You cannot edit here until a gallery is created.\n"+\
                    "    Check gallery parameters, and then "+\
                    "create an initial gallery."
        else:
            s = "    You cannot edit here until the source folder of the "+\
                "desired gallery is chosen."
        self.control.Enable()
##        self.control.SetValue(s)
        self.control.SetText(s)
        if disable:
            self.control.Enable(False)
            self.origText = "";
            self.saveButton.Enable(False)
            
        
    def getFileName(self):
        """ Return the absolute path and name of the picdocs file."""
        if self.args:
            return os.path.join(self.args[0],"picdocs.txt")
        
    def gridRow(self, grid, win, label, ctrl):
        grid.Add(wx.StaticText(win, -1, label), 0, 
                 wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)    
        grid.Add(ctrl, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)  

    def makeTupleBindNames(self, namePrefix):    
        tupleName = namePrefix + "dim"
        xName = namePrefix + "x"
        yName = namePrefix + "y"
        optionName = namePrefix + "option"
        return (tupleName, xName, yName, optionName)
        
    def setIntsFromTuple(self, obj, namePrefix):
        (tupleName, xName, yName, optionName) = self.makeTupleBindNames(namePrefix)    
        setattr(obj, xName, getattr(obj, tupleName)[0])
        setattr(obj, yName, getattr(obj, tupleName)[1])
        return (xName, yName, optionName)
    
    def setTupleFromInts(self, obj, namePrefix):
        (tupleName, xName, yName, optionName) = self.makeTupleBindNames(namePrefix)    
        setattr(obj, tupleName, (getattr(obj, xName), getattr(obj, yName))) 
                
    def createBindDimensions(self, win, obj, namePrefix, min, max, kind):
        (xName, yName, optionName) = self.setIntsFromTuple(obj, namePrefix)
        dimTooltip = "max %s of %s, initial or always.  Range min-max" 
        choiceTooltip = ("If always, require the original pics to be\n"+\
                        "symmetrically shrunk as little as possible to\n"+\
                        "%s which fit in the specified dimensions.\n"+\
                        "If initial, keep any existing %s dimensions.") \
                        % (kind, kind)   
        panel = wx.Panel(win)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(createBindIntSetter(panel, obj, xName, min, max, 
                                      tooltip = dimTooltip % ("width", kind)), 
                  0, wx.ALIGN_CENTER | wx.ALL, 0)
        sizer.Add(wx.StaticText(panel, -1, "X"), 0, wx.ALIGN_CENTER | wx.ALL, 5)    
        sizer.Add(createBindIntSetter(panel, obj, yName, min, max, 
                                      tooltip = dimTooltip % ("height", kind)), 
                  0, wx.ALIGN_CENTER | wx.ALL, 0)
        sizer.Add(createBindRadioSetter(panel, obj, optionName, 
                        ["Always", "Initial"], func = bool, 
                        tooltip = choiceTooltip),
                  0, wx.ALL, 0)
        
        panel.SetSizer(sizer)
        panel.Layout()
        return panel


    def makeGrid(self, win):
        """ parameter grid"""
        gs = wx.FlexGridSizer(0, 2, 1, 1)  # rows, cols, hgap, vgap
        self.gridRow(gs, win, "Remove blanks\nfrom filenames", 
                     createBindRadioSetter(win, self.param,"remove_blanks", 
                     ["No", "Yes"], func = bool, tooltip = 
                     "Generate picture filenames using '_' but not blanks."))
        
        self.gridRow(gs, win, "Link original (big)\nimages to the gallery ", 
                     createBindRadioSetter(win, self.param,"big_pics_linked", 
                        ["No", "Yes"], func = bool,
                        tooltip = "If no, the largest images accessible are\n"+
                        " the ones cut to fit one to a page."))
        self.gridRow(gs, win, "Lines for Titles\nUnder Thumbnails", 
                     createBindRadioSetter(win, self.param,
                        "lines_in_thumb_label", ['0', '1', '2', '3', '4', '5'],
                        tooltip = "Choose 0 if you want no title and\n"+
                        "the most thumbnails per page.  Otherwise use enough\n"+
                        "lines so all title spaces match the biggest title."))
        self.gridRow(gs, win, "Always force scaled\nimage computations", 
                     createBindRadioSetter(win, self.param, "force_conversion", 
                        ["No", "Yes"], func = bool,
                        tooltip = "Force smaller image creation from the\n"+
                        "originals even if they already exist.  This is time\n"+
                        "consuming:  only do it if you modified an original\n"+
                        "picture outside the gallery program."))
        self.gridRow(gs, win,"Thumbnail\nmax width X height", 
                     self.createBindDimensions(win, self.param, "thumb_", 
                        MIN_THUMB, MAX_THUMB, "thumbnails"))
        self.gridRow(gs, win, 
                     "Display-image\nmax width X height", 
                     self.createBindDimensions(win, self.param, "medium_", 
                        MIN_MEDIUM, MAX_MEDIUM, "display-images"))
        
        gs.AddGrowableCol(1)
        return gs
        
        
        

    def dbbCallback(self, evt):
        """Respond to the Browse button."""
        self.args = [evt.GetString()]
        self.SetStatusText(self.args[0])      
        self.setText()


    def OnTimeToClose(self, evt):
        """Event handler for the button click."""
        self.SetStatusText("See ya later!")
        self.Close()
        
    def popError(self, msg):
        """ Popup error window."""
        dlg = wx.MessageDialog(self, msg, "Gallery Error", wx.OK | wx.ICON_ERROR)
        dlg.ShowModal()
        dlg.Destroy()            
        
    
    def go(self, event):
        """ Make the gallery with the current data, add display results."""
        if not self.getFileName():
            self.SetStatusText("Choose a source folder.")
            self.popError("Choose a source folder for the gallery.")
            return
        self.onSave(None)       
        self.SetStatusText("Making gallery...wait")

        p = self.param.copy()
        self.setTupleFromInts(p, "thumb_")
        self.setTupleFromInts(p, "medium_")
        try:
            dir = main_gallery.make_gallery(self.args, p)
        except Exception, e:
            self.SetStatusText("Error in making gallery.")      
            self.popError(str(e))
            return
        
        self.args = [dir]
        self.dbb.SetValue(dir)  # also resets text
        self.SetStatusText("Gallery (re)created in %s!" % dir)
        webbrowser.open("file:///" + dir + "/index.html")


class MyApp(wx.App):
    def __init__(self, argv, param):
        self.argv = argv
        self.param = param
        wx.App.__init__(self, False) #True)
        
    def OnInit(self):
        frame = MyFrame(None, "Gallery Maker", self.argv, self.param)
        frame.Show(True)
        self.SetTopWindow(frame)
        return True

def gui(args, param):  
    app = MyApp(args, param)
    app.MainLoop()

def main(argv):
    "Choose interactive or commandline execution."
    args, param = gallery_cmd.processCmdLine(argv)
    gui(args, param)
        
#-------------------------------------------------

if __name__ == "__main__":
    main(sys.argv[1:])

