#!/usr/bin/env python

__version__ = '0.0.5'

"""

snarf /snarf/ vt.

 1. To grab, esp. to grab a large document or file for the-purpose of using it with
 or without the author's permission. See also BLT. 2. [in the Unix community] To fetch
 a file or set of files across a network. See also blast. This term was mainstream in the
 late 1960s, meaning `to eat piggishly'. It may still have this connotation in context. "He's
 in the snarfing phase of hacking -- FTPing megs of stuff a day." 3. To acquire, with little
 concern for legal forms or politesse (but not quite by stealing). "They were giving away samples,
 so I snarfed a bunch of them." 4. Syn. for slurp. "This program starts by snarfing the entire
 database into core, then...." 5. [GEnie] To spray food or programming fluids due to laughing at
 the wrong moment. "I was drinking coffee, and when I read your post I snarfed all over my desk."
 "If I keep reading this topic, I think I'll have to snarf-proof my computer with a keyboard condom."
 [This sense appears to be widespread among mundane teenagers --ESR]

"""

try:
    ''' Suppress regex deprecation warning in Python 2.1
    '''
    import warnings
    warnings.filterwarnings(action = 'ignore',
                            message='.*regex module is deprecated',
                            category=DeprecationWarning,
                            module = 'OptionFrame')
except:
    pass # Pre Python 2.1


# Python, wxPython stuff:
from wxPython.wx import *
from wxPython.lib.filebrowsebutton import FileBrowseButton
import os, os.path, string, shutil, time, sys, threading

#Import code for each notebook tab and option frame

from PanelDownload import *
from PanelUpload import *
from PanelBrowser import *
from PanelKeyBrowser import *
from PanelFmail import *
from PanelWebsite import *


# Snarfzilla stuff:

#from ID3Tag import *
#from mp3 import mp3info

# Snarfzilla paths, preferences etc. prefs.py
from prefs import *


if debug == 5:
    ''' Redirect stdout to a log file
    '''
    sys.stdout = (open("snarfzilla.log", "a"))

# Find the installation dir of snarfzilla
'''
if sys.path[0] == "":
    snarfdir = "."
else:
    snarfdir = sys.path[0]
'''

snarfdir = os.path.abspath(os.path.join(os.getcwd(), sys.path[0]))

# Allow gif, jpg, bmp, png handling for wxHtml
wxInitAllImageHandlers()

if sys.platform != 'win32':
        # Delete zero sized files in download and fmail dirs
        # Windows doesn't seem to create zero size files? CHECK THIS

        filenames = os.listdir('%s/fmail' % snarfdir)
        for filename in filenames:
            size = os.stat('%s/fmail/%s' % (snarfdir, filename))[6]
            if size == 0:
                os.unlink('%s/fmail/%s' % (snarfdir, filename))
        filenames = os.listdir('%s/download' % snarfdir)
        for filename in filenames:
            size = os.stat('%s/download/%s' % (snarfdir, filename))[6]
            if size == 0:
                os.unlink('%s/download/%s' % (snarfdir, filename))

class MyFrame(wxFrame):
    def __init__(self, parent, id, title):
        wxFrame.__init__(self, parent, -1, title,size=wxSize(800,600))
        self.SetAutoLayout(true)
        #icon = wxEmptyIcon()
        #icon.CopyFromBitmap('mocha.ico')
        iconFile = ('%s/mocha.png' % snarfdir)
        icon = wxIcon(iconFile, wxBITMAP_TYPE_PNG)
        self.SetIcon(icon)
        EVT_CLOSE(self, self.OnCloseWindow)
#--------------------------------------------------------------------------------
# Create main wxNotebook that all the panels reside in
#--------------------------------------------------------------------------------
        self.nb = wxNotebook(self, -1)
        lc = wxLayoutConstraints()
        lc.top.SameAs(self, wxTop, 0)
        lc.left.SameAs(self, wxLeft, 0)
        lc.bottom.SameAs(self, wxBottom, 0)
        lc.right.SameAs(self, wxRight, 0)
        self.nb.SetConstraints(lc)
        self.sb = self.CreateStatusBar(1, wxST_SIZEGRIP)
        #self.panlog=panellog(self.nb)
        #self.pankeyring=panelkeyring(self.nb)
        self.pandownload=paneldownload(self.nb, self.sb) #self.panlog,
        self.panfmail=panelfmail(self.nb)
        self.panupload=panelupload(self.nb, self.sb) #self.panlog,
        self.panwebsite=panelwebsite(self.nb)
        self.pankeybrowser=panelkeybrowser(self.nb, self.pandownload, self.sb)
        self.panbrowser=panelbrowser(self, self.nb, self.sb) #self.panlog,

#--------------------------------------------------------------------------------
# Setup notebook tabs
#--------------------------------------------------------------------------------

        self.nb.AddPage(self.panbrowser, "Freesite Browser")
        self.nb.AddPage(self.pankeybrowser, "Browse Keys")
        self.nb.AddPage(self.pandownload, "Download")
        self.nb.AddPage(self.panupload, "Upload")
        self.nb.AddPage(self.panfmail, "Fmail")
        self.nb.AddPage(self.panwebsite, "Create Freesite")
        #self.nb.AddPage(self.pancreate, "Create Catalog") # ESPRA
        #self.nb.AddPage(self.pankeyring, "Keyring")
        #self.nb.AddPage(self.panlog, "Log")


#--------------------------------------------------------------------------------
# Toolbar is borked in Windows, images too big.
#--------------------------------------------------------------------------------
        if sys.platform != 'win32':
            import images
            newFmailID = wxNewId()
            checkFmailID = wxNewId()
            replyFmailID = wxNewId()
            deleteFmailID = wxNewId()
            abookFmailID = wxNewId()
            self.tb = self.CreateToolBar(wxTB_HORIZONTAL|wxNO_BORDER|wxTB_FLAT)
            self.tb.AddSimpleTool(newFmailID, wxBitmap('Images/fmail_new.bmp', wxBITMAP_TYPE_BMP ) , "Compose New Fmail", "Compose New Mail")
            self.tb.AddSimpleTool(checkFmailID, wxBitmap('Images/fmail_check.bmp', wxBITMAP_TYPE_BMP ) , "Check For New Fmail", "Check for new Mail")
            self.tb.AddSimpleTool(replyFmailID, wxBitmap('Images/fmail_reply.bmp', wxBITMAP_TYPE_BMP ) , "Reply to Fmail", "Reply to Mail")
            self.tb.AddSimpleTool(deleteFmailID, wxBitmap('Images/fmail_del.bmp', wxBITMAP_TYPE_BMP ) , "Delete Fmail", "Delete selected Mail")
            self.tb.AddSimpleTool(abookFmailID, wxBitmap('Images/fmail_abook.bmp', wxBITMAP_TYPE_BMP ) , "Fmail Address Book", "Fmail Address Book")
            self.tb.Realize()
            EVT_TOOL(self, newFmailID, self.OnMnuSendFmail)
            EVT_TOOL(self, checkFmailID, self.OnMnuFetchFmail)
            EVT_TOOL_ENTER(self, -1, self.OnToolZone)
            EVT_TIMER(self, -1, self.OnClearSB)
            self.timer = None
#--------------------------------------------------------------------------------
# Menu bar
#--------------------------------------------------------------------------------
        # File
        menu_file = wxMenu()
        mnuexitID=NewId()
        menu_file.Append(mnuexitID, "E&xit")
        menubar = wxMenuBar()
        menubar.Append(menu_file, "&File")
        # Options
        #win32
        '''
        menu_options = wxMenu()
        mnuSnarfPrefID = NewId()
        menu_options.Append(mnuSnarfPrefID, "Snarfzilla Preferences")
        menubar.Append(menu_options, "&Options")
        '''
        # Tools
        menu_tools = wxMenu()
        mnuCreateDBRID = NewId()
        menu_tools.Append(mnuCreateDBRID, "Create DBR")
        menubar.Append(menu_tools, "&Tools")
        # Fmail
        menu_fmail = wxMenu()
        mnuSendFmailID = NewId()
        mnuFetchFmailID = NewId()
        menu_fmail.Append(mnuFetchFmailID, "Fetch Fmail")
        menu_fmail.Append(mnuSendFmailID, "Send Fmail")
        menubar.Append(menu_fmail, "F&mail")
        # Keys
        menu_keys = wxMenu()
        mnuGenKeysID = NewId()
        mnuSendKeyToIndexID = NewId()
        #mnuAddWebIndexID = NewId()
        mnuAddIFIndexID = NewId()
        menu_keys.Append(mnuGenKeysID, "Generate SSK Keypair")
        menu_keys.Append(mnuSendKeyToIndexID, "Send Key to Index")
        #menu_keys.Append(mnuAddWebIndexID, "Add Web Key Index")
        #menu_keys.Append(mnuAddIFIndexID, "Add In-Freenet Key Index")
        menubar.Append(menu_keys, "&Keys")
        # Help
        menu_help = wxMenu()
        mnuhelpID=NewId()
        mnuaboutID=NewId()
        menu_help.Append(mnuhelpID,"Contents")
        menu_help.Append(mnuaboutID,"About")
        menubar.Append(menu_help,"&Help")
        self.SetMenuBar(menubar)
        EVT_MENU(self, mnuexitID, self.OnMnuExit)
        #win32
        #EVT_MENU(self, mnuSnarfPrefID, self.OnMnuSnarfPref)
        EVT_MENU(self, mnuaboutID, self.OnMnuAbout)
        EVT_MENU(self, mnuhelpID, self.OnMnuHelp)
        EVT_MENU(self, mnuGenKeysID, self.OnMnuGenKeys)
        EVT_MENU(self, mnuCreateDBRID, self.OnMnuCreateDBR)
        EVT_MENU(self, mnuSendFmailID, self.OnMnuSendFmail)
        EVT_MENU(self, mnuFetchFmailID, self.OnMnuFetchFmail)
        EVT_MENU(self, mnuSendKeyToIndexID, self.OnMnuSendKeyToIndex)
#--------------------------------------------------------------------------------
# Keyboard accelerators
#--------------------------------------------------------------------------------

        # Alt-X to exit
        # TODO: Add for each item in menu
        aTable = wxAcceleratorTable([(wxACCEL_ALT,  ord('X'), mnuexitID)])
        self.SetAcceleratorTable(aTable)

        EVT_NOTEBOOK_PAGE_CHANGED(self.nb, self.nb.GetId(), self.OnPageChanged)

        seconds = string.atoi(fmailInterval)
        if seconds:
            self.ftimer = FmailTimer(self)
            self.ftimer.Start(seconds)  # Start the update timer  once each 10

        filenames = os.listdir('%s/fmail' % snarfdir)
        fmailList = {}
        for fmail in filenames:
            #filesize = os.stat('%s/fmail/%s' % (snarfdir, fmail))[6]
            #ttlFileSize = filesize
            status = "Old"
            nbrDashes = string.count(fmail, '-')
            if nbrDashes:
                fmailList[fmail] = status

        keys = fmailList.keys()
        keys.sort()
        for key in keys:
            self.panfmail.AddKeyToRow(key, fmailList[key])

    def OnToolZone(self, event):
        if self.timer is None:
            self.timer = wxTimer(self)
        if self.timer.IsRunning():
            self.timer.Stop()
        self.timer.Start(3000)
        event.Skip()

    def OnClearSB(self, event):  # called for the timer event handler OnToolZone
        self.SetStatusText("") # Clear status bar after hovering over toolbar icon
        self.timer.Stop()
        self.timer = None

    def OnPageChanged(self, event):
        event.Skip()
        self.nbPage = event.GetSelection()
        #self.tb.Hide()
        #print self.nb.GetPageText(self.nbPage)

    def OnMnuSendKeyToIndex(self,event):
        """ Send keys to multiple in-Freenet key indexes (threaded)
        """
        dlg = wxTextEntryDialog(self, "Enter Key:\n\n",
                                      'Send Key to Index', '')
        if dlg.ShowModal() == wxID_OK:
            key = dlg.GetValue()
            dlg.Destroy()
            if key:
                from wxPython.lib.dialogs import wxMultipleChoiceDialog
                lst = [ 'freegle', 'snarfoo', 'punk-mp3', 'blues-mp3', 'rock-mp3' ] #TODO Take from file!
                dlg2 = wxMultipleChoiceDialog(self, "Choose One Or\nMore Key Indexes\n\nIn-Freenet Key Indexes:", "Send Key To Index", lst)
                if (dlg2.ShowModal() == wxID_OK):
                    print "Selection:", dlg2.GetValue(), " -> ", dlg2.GetValueString()
                    list = dlg2.GetValueString()
                    from submitKeyIF import submitKey
                    htl = 30
                    for indexname in list:
                        print ("Submitting to: %s" % indexname)
                        sendID = submitKey(self, key, indexname, htl)
                        sendID.start()
                dlg2.Destroy()

    def OnFetchFmail(self, indexname):
        now = int(time.time()) # Seconds since Epoch
        midnight = now - (now % 86400) # GMT Midnight
        max = 2
        nbr = 0
        while nbr < max:
            box = ('%s-%s-%s' % (indexname, midnight, nbr))
            if os.path.exists('%s/fmail/%s' % (snarfdir, box)):
                #if os.stat('%s/fmail/%s' % (snarfdir, box))[6]:
                max = max + 1
                nbr = nbr + 1
            else:
                self.panfmail.AddKeyToRow(box, 'Queued')
                nbr = nbr + 1

    def OnMnuFetchFmail(self, event):
        #win32
        f = open('%s/fmail/boxes.txt' % snarfdir)
        boxes = f.readlines()
        for box in boxes:
            self.OnFetchFmail(string.strip(box))

        '''
        dlg = wxTextEntryDialog(self, "Enter Index Name:\n\n",
                                'Fetch Fmail', '')
        if dlg.ShowModal() == wxID_OK:
            indexname = dlg.GetValue()
            dlg.Destroy()
            if indexname:
                now = int(time.time()) # Seconds since Epoch
                midnight = now - (now % 86400) # GMT Midnight
                max = 5
                inc = 0
                while inc < max:
                    indexdate = ('%s-%s-%s' % (indexname, midnight, inc))
                    #timetuple = time.localtime(midnight)
                    timetuple = time.gmtime(midnight)
                    date = time.strftime(" %d %b %Y", timetuple)
                    #alreadyChecking = self.panfmail.Checking(indexdate)
                    #if not alreadyChecking:
                    self.panfmail.AddKeyToRow(indexdate, 'Queued')
                    inc = inc + 1
                    #else:
                    #    max = max + 1
                self.nb.SetSelection(4)
        else: # Pressed Cancel
            dlg.Destroy()
        #print self.panfmail.CountItems()
        #print self.panfmail.CountBusy()
        '''

    def OnMnuSendFmail(self,event):
        from SendFmailFrame import *
        a = sendFmailFrame(None, -1, "Send Fmail")
        a.Show(true)

    def OnMnuGenKeys(self,event):
        '''
        TODO: Use XML-RPC to generate keys when freenet.jar is fixed (0.3.9.2?)
        '''

        dlg = wxTextEntryDialog(self, "What name do you want to give this keypair?\n\n (Leave blank if you don't want to save to disk)",
                                      'SSK Keypair Generator', '')
        if dlg.ShowModal() == wxID_OK:
            keyname = dlg.GetValue()
            #dlg.Destroy()
            if keyname:
                #win32
                finsert = (r"\Freenet\Finsert")
                cmd = ('%s --makeKeypair > \snarfzilla\keys\%s.key' % (finsert, keyname))
                print cmd
                os.system(cmd)
                #os.system('%s%s%s --makeKeypair > keys%s%s.key' % (freenetdir, os.sep, finsert, os.sep, keyname))
                #win32
                msg = ('Your keypair is in:\n\n \snarfzilla\keys\%s.key' % (keyname))
                #msg = ('Your keypair is in:\n\n %s/keys/%s.key' % (freenetdir, keyname))
                dlg2 = wxMessageDialog(self, msg, 'Done.',
                                       wxOK | wxICON_INFORMATION)
                dlg2.ShowModal()
                dlg2.Destroy()
            else:
                dlg.Destroy()
                from wxPython.lib.dialogs import wxScrolledMessageDialog
                #win32
                finsert = (r"\Freenet\Finsert")
                tmpFile = (r"\Snarfzilla\Tmpkey")
                os.system('%s --makeKeypair > %s' % (finsert, tmpFile))
                #os.system('%s%s%s --makeKeypair > %s%stmpkey' % (freenetdir, os.sep, finsert, snarfdir, os.sep))
                #tmpFile = '\snarfzilla\tmpkey'
                f = open(tmpFile, 'r')
                keys = f.readlines()
                f.close()
                os.unlink(tmpFile)
                privkey = keys[1]
                pubkey = keys[2]
                keys = privkey + pubkey
                dlg2 = wxScrolledMessageDialog(self, keys, 'Your SSK Keypair:')
                dlg2.ShowModal()
                dlg2.Destroy()
        else:
            dlg.Destroy()

    def OnMnuCreateDBR(self,event):
        dlg1 = wxTextEntryDialog(self, "Enter your Private SSK:\n\n",
                                 'Create DBR', '')
        if dlg1.ShowModal() == wxID_OK:
            keyname = dlg1.GetValue()
            dlg1.Destroy()
            if keyname:
                dlg2 = wxTextEntryDialog(self, "Enter your site name:\n\n",
                                         'Create DBR', '')
                if dlg2.ShowModal() == wxID_OK:
                    sitename = dlg2.GetValue()
                    dlg2.Destroy()
                    if sitename:
                        try:
                            keysite = ('%s/%s' % (keyname, sitename))
                            dlg3 = wxMessageDialog(self, 'This will take a few minutes. Press OK to begin.', 'Ready to begin.',
                                   wxOK | wxICON_INFORMATION)
                            dlg3.ShowModal()
                            dlg3.Destroy()
                            wxYield()
                            #win32
                            dbr = CreateDBR(keysite)
                            dbr.start()
                            dlg4 = wxMessageDialog(self, "DBR Creation in progress.\nDon't shut down for 10 mintes.", 'Done.',
                                   wxOK | wxICON_INFORMATION)
                            dlg4.ShowModal()
                            dlg4.Destroy()
                        except:
                            dlg3 = wxMessageDialog(self, 'Initial DBR creation failed', 'Failure.',
                            wxOK | wxICON_INFORMATION)
                            dlg3.ShowModal()
                            dlg3.Destroy()

    def OnMnuHelp(self, event):
        import Help
        if snarfdir == ".":
            helpdir = "index.html"
        else:
            #helpdir = ('%s/Docs/index.html' % snarfdir)
            helpdir = 'index.html'
        Help.showHelp(self, Help.BoaHelpFrame, '%s' % helpdir) #snarfzilla.0.0.x/Docs/index.html

    def OnMnuExit(self,event):
        self.Close()

    def OnMnuSnarfPref(self, event):
        from OptionFrame import *
        a = optionSnarfFrame(None, -1, "Snarfzilla Preferences")
        a.Show(true)

    def OnMnuAbout(self,event):
        dlg = wxMessageDialog(self, 'Snarfzilla is a Python and wxPython Freenet application\n by Rob Cakebread released under the GPL license.\n\n',
                              'About Snarfzilla', wxOK | wxICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def OnCloseWindow(self, event):
        '''
        TODO: Maybe warn user about downloads in progress etc before closing Snarfzilla.
        '''
        if sys.platform != 'win32':
                # Delete zero sized files in download and fmail dirs
                # Windows doesn't seem to create zero size files? CHECK THIS

                filenames = os.listdir('%s/fmail' % snarfdir)
                for filename in filenames:
                    size = os.stat('%s/fmail/%s' % (snarfdir, filename))[6]
                    if size == 0:
                        os.unlink('%s/fmail/%s' % (snarfdir, filename))

                filenames = os.listdir('%s/download' % snarfdir)
                for filename in filenames:
                    size = os.stat('%s/download/%s' % (snarfdir, filename))[6]
                    if size == 0:
                        os.unlink('%s/download/%s' % (snarfdir, filename))
        self.Destroy()


class FmailTimer(wxTimer):
    def __init__(self, parent):
        wxTimer.__init__(self)
        self.parent = parent

    def Notify(self):
        #win32
        f = open('%s/fmail/boxes.txt' % snarfdir)
        boxes = f.readlines()
        for box in boxes:
            box = string.strip(box)
            self.parent.OnFetchFmail(box)

class CreateDBR(threading.Thread):
    def __init__(self, keysite):
        threading.Thread.__init__(self)
        self.setDaemon(1)
        self.keysite = keysite

    def run(self):
        from prefs import *
        finsert = (r"\Freenet\Finsert.exe")
        os.system('%s -h 35 --serverAddress %s -c %s' % (finsert, serverAddress, self.keysite))

class MyApp(wxApp):
    def OnInit(self):
        title = ''
        frame=MyFrame(None, -1, title)
        frame.Show(true)
        self.SetTopWindow(frame)
        return true



app=MyApp(0)
app.MainLoop()