## ------------------------------------------------------------------------
## iSiLK - A python-based graphical user interface for SiLK
## ------------------------------------------------------------------------
## Copyright (c) 2007-2008 Carnegie Mellon University. All Rights Reserved.
## ------------------------------------------------------------------------
## Authors: Andrew Kompanek (ajk@cert.org)
## ------------------------------------------------------------------------
## GNU General Public License (GPL) Rights pursuant to Version 2, June 1991
## Government Purpose License Rights (GPLR) pursuant to DFARS 252.225-7013
## ------------------------------------------------------------------------
## See the LICENSE file included in this distribution
## ------------------------------------------------------------------------

import wx
import wx.html
import wx.lib.fancytext
import ws
import string
from datacache import formatFieldAsString
from constants import *
from analysisresult import ProblemSet
import config.silk
    
class InfoPanel(wx.Panel):
    
    instances = {}
    
    # Update content that can change during the lifetime of the result
    def _UpdateContent(self):
        if not config.silk.workRemotely() and self.dataset.IsLocalFileAvailable():
            loc_str = "%s" % (self.dataset.GetLocalPath())
        else:
            loc_str = "%s:%s" % (self.dataset.GetRemoteHost(), 
                self.dataset.GetRemotePath())
        self.title.SetValue(self.dataset.GetName())
        self.notes.SetValue(self.dataset.GetNotes())
        self.loc.SetLabel(loc_str)
        
        if self.showCommands:
           content_str = "<html><body><br><font size='-1'><tt>" 
           for l in self.dataset.GetInfo()["command-lines"]:   
              content_str += "%s<br><br>" % l    
           content_str += "</tt></font></body></html>"
           self.cmds.SetPage(content_str)
           
    def GetDataObject(self):
        return self.dataset
       
    def __init__(self, dataset, parent):
         row = -1
         wx.Panel.__init__(self, parent, -1)
         self.dataset = dataset
         self.showCommands =  self.dataset.GetInfo() and "command-lines" in self.dataset.GetInfo()
   
         # Name, filename and directory
         if isinstance(self.dataset, ProblemSet):
             style = wx.TE_READONLY
         else:
             style = wx.TE_PROCESS_ENTER
         self.title = wx.TextCtrl(self, -1, "", style=style, validator=ws.NameValidator())
         # FIXME: hack for right now

         self.title.SetFont(ws.LgFont(wx.SWISS, wx.NORMAL, wx.BOLD))
         self.loc = ws.SmStaticLabel(self, -1, "")
         # Notes
         self.notes = wx.TextCtrl(self, -1, style=wx.TE_MULTILINE, size=(-1, 100))
         # Command lines
         if self.showCommands:
             self.cmds_label = ws.SmStaticLabel(self, -1, "Command line history")
             self.cmds = wx.html.HtmlWindow(self, -1, style=wx.SIMPLE_BORDER)

         # Update the values
         self._UpdateContent()
         self.notes.SetFocus()

         # Pack controls
         sz = wx.GridBagSizer()
         # This is necessary on Windows XP to ensure static lines aren't "fat"
         sz.SetEmptyCellSize((0,0))
         l = [ (row,0) for row in range(0,6) ] 
         def _pos(l): return l.pop(0)
         sz.Add(self.title, 
            _pos(l), (1,3), flag=wx.EXPAND|wx.ALL, border=8)
         sz.Add(self.loc,
            _pos(l), (1,3), flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM, border=8)
         line = wx.StaticLine(self, size=(200,-1), style=wx.LI_HORIZONTAL)
         sz.Add(line, _pos(l), (1,3), wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER|wx.TOP|wx.BOTTOM, border=4)
         sz.Add(ws.SmStaticText(self, -1, "Notes"),
            _pos(l), (1,3), flag=wx.ALL,border=8)
         sz.Add(self.notes,
            _pos(l), (1,3), flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM, border=8)

         header_fields = ["format(id)", "version", "byte-order",
             "compression(id)", "header-length", "record-length",  
             "count-records", "file-size"]
         row = 6
         info = self.dataset.GetInfo()
         if info:
             if len(info.keys()) > 0:
                 sz.Add(wx.StaticLine(self, size=(200,-1), style=wx.LI_HORIZONTAL),
                    _pos(l), (1,3), wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER|wx.BOTTOM, border=8)
             
             for f in [ x for x in header_fields if x in info]:
                     sz.Add(ws.SmBoldStaticLabel(self, -1, f+":"),
                        (row, 0), (1,1), flag=wx.ALIGN_RIGHT|wx.LEFT, border=20)
                     val = info[f]
                     if f == "file-size" or f == "header-length" or f=="record-length":
                         val = formatFieldAsString("bytes", val) + " bytes"
                     if f == "count-records":
                         val = formatFieldAsString("records", val) + " records"
                     sz.Add(ws.SmStaticLabel(self, -1, val), (row,1), (1,1), 
                              flag=wx.RIGHT|wx.LEFT|wx.ALIGN_LEFT, border=4)
                     row = row + 1 
         if self.showCommands:
             sz.Add(wx.StaticLine(self, style=wx.LI_HORIZONTAL), 
                 (row,0), (1,3), flag=wx.EXPAND|wx.TOP|wx.BOTTOM, border=8)
             row += 1
             sz.Add(self.cmds_label, (row,0), (1,3), 
                    flag=wx.EXPAND|wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM, border=4)
             row += 1
             sz.Add(self.cmds, (row,0), (1,3),
                    flag=wx.EXPAND|wx.GROW|wx.ALL, border=2)              
             sz.AddGrowableRow(row)
         sz.AddGrowableCol(2)
         self.SetSizerAndFit(sz)
         # Event handlers
         self.Bind(wx.EVT_TEXT_ENTER, self.UpdateDataSet, self.title)
         self.Bind(wx.EVT_TEXT_ENTER, self.UpdateDataSet, self.notes)
         self.title.Bind(wx.EVT_SET_FOCUS, self.UpdateDataSet)
         self.notes.Bind(wx.EVT_SET_FOCUS, self.UpdateDataSet)
         if self.showCommands:
             self.cmds.Bind(wx.EVT_SET_FOCUS, self.UpdateDataSet)
         self.title.SetFocus()
         # Make sure that the whole title is visible (hack needed under XP)
         self.title.SetInsertionPoint(0)
         self.notes.SetFocus()
 
         
    def UpdateDataSet(self, event):
        print "UPDATING"
        #busy = wx.BusyInfo("Renaming files", self)
        self.dataset.SetName(self.title.GetValue())
        self.dataset.SetNotes(self.notes.GetValue())
        self._UpdateContent()
        print "Set name and notes"
                
    def OnTitleChange(self, event):
        print "OnTitleChange"
        busy = wx.BusyInfo("Renaming files")        
        print "Changed title to %s" % self.title.GetValue()
        self.dataset.SetName(self.title.GetValue())
        
    def OnNotesChange(self, event):
        print "OnNotesChange"
        self.dataset.SetNotes(self.notes.GetValue())


class InfoFrame(wx.Frame):
    instances = {}
    def ShowPanel(dataset, parent, pos=wx.DefaultPosition, size=wx.DefaultSize, 
        style=wx.DEFAULT_FRAME_STYLE):
        if dataset in InfoFrame.instances:
            InfoFrame.instances[dataset].Show(False)
            InfoFrame.instances[dataset].Show(True)
            return InfoFrame.instances[dataset]
        else:
            f = InfoFrame.instances[dataset] = InfoFrame(dataset, parent,
                    pos, size, style)
            f.Show(True)
            return f
    ShowPanel = staticmethod(ShowPanel)

    def __init__(self, dataset, parent, pos=wx.DefaultPosition, size=wx.DefaultSize, 
                 style=wx.DEFAULT_FRAME_STYLE ):
        title = "Info for %s" % dataset.GetName()
        wx.Frame.__init__(self, parent, -1, title, pos, size, style)
        self.dataset = dataset 
        if wx.Platform == "__WXMAC__":
            menuBar = wx.GetApp().CreateMenuBar()   
            self.SetMenuBar(menuBar)
        self.panel = panel = InfoPanel(dataset, self)
        self.Bind(wx.EVT_MENU, self.OnCloseWindow, id=ID_CLOSE_WINDOW)
        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
        (w, h)= self.GetBestSize();
        if self.panel.showCommands:
            h += 160 # add this since html control doesn't tell us its size
        self.SetMinSize((w,h))
        self.SetSize((w,h))
         
    def OnCloseWindow(self, event):
        self.panel.UpdateDataSet(event)
        self.Destroy()
        del InfoFrame.instances[self.dataset]
