from wxPython.wx import *
import os, urllib, sys, threading
from prefs import *

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

'''
Recent CHANGES:

Stripped \n\n for Windows in wxListCtl
'''

class panelkeybrowser(wxPanel):

    """
    TODO:
        * Save keylists and let user retrieve later

        * Add key index servers on the fly

        * Brief key names toggles filename from key in listctrl

    """

    def __init__(self, parent, downloadTab, sb):
        wxPanel.__init__(self, parent, -1)
        self.sb = sb # Statusbar
        self.downloadTab = downloadTab
        searchId = wxNewId()
        choiceId = wxNewId()
        serverList = ['Thalassocracy', 'Freegle']
        self.server = 'Thalassocracy' # Default choice web key index
        self.IFserver = 'freegle' # Default choice in freenet keyindex
        self.choiceBox = wxChoice(self, choiceId, choices = serverList)
        self.lblSearch = wxStaticText(self, -1, "Search: " )
        self.inpSearch = wxTextCtrl(self, searchId, '', style=wxTE_PROCESS_ENTER)
        # Add to sizers
        boxWeb = wxBoxSizer(wxHORIZONTAL)
        boxWeb.Add(self.lblSearch, 0, wxLEFT, 5)
        boxWeb.Add(self.inpSearch, 1, wxALIGN_LEFT, 5)
        boxWeb.Add(10, 20, 0, wxEXPAND)
        boxWeb.Add(self.choiceBox, 1, wxALIGN_LEFT, 5)
        boxNameWeb = wxStaticBox( self, -1, "Web Index" )
        borderWeb = wxStaticBoxSizer( boxNameWeb, wxHORIZONTAL )
        borderWeb.Add( boxWeb, 0, wxALL | wxALIGN_LEFT, 5 )

        InFreenetList = ['freegle', 'snarfoo']
        self.keyindex = 'freegle' # Default choice
        sendID = wxNewId()
        IFchoiceID = wxNewId()
        EVT_CHOICE(self, choiceId, self.EvtChoice)
        EVT_CHOICE(self, IFchoiceID, self.EvtChoiceIF)
        self.InFreenetChoiceBox = wxChoice(self, IFchoiceID, choices = InFreenetList)
        boxInFreenet = wxBoxSizer(wxHORIZONTAL)
        self.SendBtn = wxButton(self, sendID, 'Search')
        EVT_BUTTON(self, sendID, self.EvtQueIFkeys)
        boxInFreenet.Add(self.InFreenetChoiceBox, 1, wxALIGN_LEFT, 5)
        boxInFreenet.Add(10, 20, 0, wxEXPAND)
        boxInFreenet.Add(self.SendBtn, 1, wxALIGN_LEFT, 5)
        boxNameInFreenet = wxStaticBox( self, -1, "In-Freenet Index" )
        borderIF = wxStaticBoxSizer( boxNameInFreenet, wxHORIZONTAL )
        borderIF.Add( boxInFreenet, 0, wxALL | wxALIGN_LEFT, 5 )

        #boxOther = wxBoxSizer(wxHORIZONTAL)
        fromFileID = wxNewId()
        self.fromFileBtn = wxButton(self, fromFileID, 'Load File')
        self.fromFileBtn.SetToolTip(wxToolTip("Load list of keys from plain text file"))
        #fromFileID = wxNewId()
        #self.FromFileBtn = wxButton(self, fromFileID, 'Load')
        #boxOther.Add(self.FromFileBtn, 1, wxALIGN_LEFT, 5)
        #boxOther.Add(self.ClipboardBtn, 1, wxALIGN_LEFT, 5)
        boxNameOther = wxStaticBox(self, -1, "Keys From File")
        borderOther = wxStaticBoxSizer(boxNameOther, wxHORIZONTAL)
        borderOther.Add(self.fromFileBtn, 0, wxALL | wxALIGN_LEFT, 5)

        boxIndexes = wxBoxSizer(wxHORIZONTAL)
        boxIndexes.Add(borderWeb, 0, wxALL, 5)
        boxIndexes.Add(borderIF, 0, wxALL, 5)
        boxIndexes.Add(borderOther, 0, wxALL, 5)

        # Hookup all the events to controls
        EVT_BUTTON(self, fromFileID, self.OnFromFile)
        EVT_CHOICE(self, choiceId, self.EvtChoice)
        EVT_CHAR(self.inpSearch, self.EvtSearchEnter)

        self.notebook = 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.notebook.SetConstraints(lc)
        #self.panel=tabPanel(self.notebook, self.downloadTab)
        #self.notebook.AddPage(self.panel, "Results")
        boxNotebook = wxBoxSizer(wxHORIZONTAL)
        boxNotebook.Add(self.notebook, 1, wxEXPAND|wxALL,0)

        #Events:

        EVT_NOTEBOOK_PAGE_CHANGED(self.notebook, self.notebook.GetId(), self.OnPageChanged)
        #Put everything into a sizer
        sizer = wxBoxSizer(wxVERTICAL)
        sizer.Add(boxIndexes, 0, wxEXPAND, 5)
        #sizer.Add(boxResults, 1, wxEXPAND|wxALL, 5)
        sizer.Add(boxNotebook, 1, wxEXPAND|wxALL, 5)
        #sizer.Add(boxOther, 1, wxEXPAND|wxALL, 5)
        self.SetSizer(sizer)
        self.SetAutoLayout(true)

    def OnPageChanged(self, event):
        event.Skip()
        self.nbPage = event.GetSelection()

    def DelPage(self):
        #print self.nbPage
        self.notebook.RemovePage(0)

    def EvtChoice(self, event):
        self.server = event.GetString()

    def EvtChoiceIF(self, event):
        self.IFserver = event.GetString()

    def OnFromFile(self, event):
        dlg = wxFileDialog(self, "Choose a file", ".", "", "*", wxOPEN|wxMULTIPLE)
        if dlg.ShowModal() == wxID_OK:
            for file in dlg.GetPaths():
                pass
        dlg.Destroy()
        size = ''
        path, index = os.path.split(file)
        fileType = ''
        file = open(file, 'r')
        self.panel=tabPanel(self.notebook, self.downloadTab, 'notFreegle')
        self.notebook.AddPage(self.panel, ('File: %s' % (index)))
        key = file.readline()
        if key:
            string.strip(key)
            self.panel.AddRow(key, fileType, size)
        while key:
            key = file.readline()
            if key:
                string.strip(key)
                self.panel.AddRow(key, fileType, size)
        self.SetLastPage()

    def SetLastPage(self):
        lastPage = self.notebook.GetPageCount() -1
        self.notebook.SetSelection(lastPage)
        self.inpSearch.SetFocus()

    def EvtSearchEnter(self, event):
        keyPressed = event.GetKeyCode()
        if keyPressed == 13: # Enter key
            searchValue = self.inpSearch.GetValue()  # Get url from search input box
            if self.server == "Thalassocracy":
                url = ('http://azrael.dyn.cheapnet.net/cgi-bin/keysearch/?key=%s' % searchValue)
                searchType = 'notFreegle'
            if self.server == "Freegle":
                url = ('http://www.freegle.com:8778/formachines/search/?s=%s' % searchValue)
                searchType = 'freegle'
            self.panel=tabPanel(self.notebook, self.downloadTab, searchType)
            self.notebook.AddPage(self.panel, ('%s : %s' % (searchValue, self.server)))
            doSearch = getKey(self.panel, self.server, url, searchValue)
            doSearch.start()
            self.inpSearch.SetValue('')
            self.SetLastPage()
            #self.AddRedRow('Searching for %s...' % searchValue)
        event.Skip()

    def EvtQueIFkeys(self, event):
            self.panel=tabPanel(self.notebook, self.downloadTab, 'notFreegle')
            self.notebook.AddPage(self.panel, ('%s in-Freenet' %  self.IFserver))
            doSearch = getInFreenetKey(self.panel, self.IFserver)
            doSearch.start()
            #self.panel.AddRedRow('Searching in-Freenet key indexes is slow. Please be patient.')
            self.SetLastPage()


class getInFreenetKey(threading.Thread):
    '''
    TODO: We should get rid of dependency on java KeyIndexClient
    '''

    def __init__(self, panel, server):
        threading.Thread.__init__(self)
        self.setDaemon(1)
        self.IFserver = server
        self.panel = panel
    def run(self):
        filename = ('%s.txt' % self.IFserver)
        #win32
        cmd = ('%s -cp /freenet/freenet.jar Freenet.client.KeyIndexClient -htl 40 -list %s > %s' % (java, self.IFserver, filename))
        #cmd = ('%s -cp %s/freenet.jar Freenet.client.KeyIndexClient -htl 40 -list %s > %s' % (java, freenetdir, self.IFserver, filename))
        ttlKeys = 0
        self.panel.AddRedRow("Searching, please be patient...")
        try:
            os.system(cmd)
            f = open(filename, 'r')
            key = f.readline() # Ignore first line
            while key:
                key = f.readline()
                if key:
                    ttlKeys = ttlKeys + 1
                    self.panel.AddRow(key, '', '')
            f.close()
            if ttlKeys == 3:
                ttlKeys = 0
                self.panel.EvtClearAll(None)
            nbrItems = self.panel.GetItemCount()
            if nbrItems:
                self.panel.DelRow(nbrItems - 1) # Delete 'Searching...' message
            msg = ("Found %s keys." % ttlKeys)
            self.panel.AddRedRow(msg)

        except:
            pass
            # Probably tried same search twice TODO: use tempfile more sanely
        try:
            os.remove(filename)
        except:
            pass
            # Probably tried same search twice TODO: use tempfile more sanely

class getKey(threading.Thread):
    def __init__(self, panel, server, url, searchValue):
        threading.Thread.__init__(self)
        self.setDaemon(1)
        self.server = server
        self.url = url
        self.searchValue = searchValue
        self.panel = panel

    def run(self):
        if self.server == 'Freegle':
            self.Freegle()
        else:
            self.Plain()

    def Plain(self):
        '''
        This method retrieves a list of keys from a url.
        Keys are one per line in a plain text file.
        '''

        filein = urllib.urlopen(self.url)
        key = filein.readline()
        key = string.strip(key)
        ttlKeys = 0
        if key:
            ttlKeys = ttlKeys + 1
            self.panel.AddRow(key, '', '')
        while key:
            key = filein.readline()
            key = string.strip(key)
            if key:
                ttlKeys = ttlKeys + 1
                self.panel.AddRow(key, '', '')
        msg = ('Found %s keys.' % ttlKeys)
        self.panel.AddRedRow(msg)

    def Freegle(self):
        '''
        Downloads list of keys from freegle.com.
        Format returned is:

        total=31
        End
        contentType=audio/mpeg
        key=KSK@mp3/stefan+poiss/cosmotron2.mp3
        score=33
        size=>1000000
        End...
        '''

        filein = urllib.urlopen(self.url)
        ttlKeys = 0
        ttl = filein.readline()
        ttl = string.split(ttl, '=')[1]
        ttl = string.strip(ttl)
        doit = 1
        while doit:
            try:
                end = filein.readline()
                fileType = filein.readline()
                fileType = string.split(fileType, "=")[1]
                fileType = string.split(fileType, "/")[1]
                #fileType = string.strip(fileType)
                key = filein.readline()
                key = string.split(key, "=")[1]
                #key = string.strip(key)
                score = filein.readline()
                size = filein.readline()
                size = string.split(size, "=")[1]
                #size = strip.string(size)
                self.panel.AddRow(key, fileType, size)
            except:
                msg = ('Found %s keys.' % ttl)
                self.panel.AddRedRow(msg)
                break

class tabPanel(wxPanel):
    def __init__(self, notebook, downloadTab, searchType):
        wxPanel.__init__(self, notebook, -1)
        self.SetAutoLayout(true)
        self.notebook = notebook
        self.downloadTab = downloadTab
        self.searchType = searchType
        klistID = wxNewId()
        self.klist= wxListCtrl(self, klistID, size=wxDefaultSize,style=wxLC_REPORT|wxSUNKEN_BORDER)
        self.klist.InsertColumn(0,"Key")
        if self.searchType == 'freegle':
            self.klist.InsertColumn(1,"File Type")
            self.klist.InsertColumn(2,"Size")

        if self.searchType == 'freegle':
            self.klist.SetColumnWidth(0, 490)
            self.klist.SetColumnWidth(1, 90)
            self.klist.SetColumnWidth(2, 90)
        else:
            self.klist.SetColumnWidth(0, 700)
        sizer = wxBoxSizer(wxHORIZONTAL)
        sizer.Add(self.klist, 1, wxEXPAND|wxALL,0)
        self.SetSizer(sizer)
        self.SetAutoLayout(true)

        #Event handling:
        # for wxMSW
        EVT_COMMAND_RIGHT_CLICK(self.klist, klistID, self.OnRightClick)
        # for wxGTK
        EVT_RIGHT_UP(self.klist, self.OnRightClick)
        EVT_RIGHT_DOWN(self.klist, self.OnRightDown)
        EVT_LIST_ITEM_SELECTED(self, klistID, self.OnItemSelected)
        EVT_LIST_ITEM_ACTIVATED(self, klistID, self.OnDoubleClick) # Double-click or Enter pressed

    def RemoveTab(self, event):
        currentPage = self.notebook.GetSelection()
        #win32
        self.notebook.RemovePage(currentPage)
        self.notebook.SetSelection(0)
        
    def AddRow(self, key, fileType, size):
        key = string.strip(key)
        fileType = string.strip(fileType)
        size = string.strip(size)
        self.klist.InsertStringItem(0, key)
        if self.searchType == 'freegle':
            self.klist.SetStringItem(0, 1, fileType)
            self.klist.SetStringItem(0, 2, size)

    def DelRow(self, row):
        self.klist.DeleteItem(row)

    def GetItemCount(self):
        return self.klist.GetItemCount()

    def OnItemSelected(self, event):
        self.currentItem = event.m_itemIndex
        #print self.currentItem

    def OnRightDown(self, event):
        self.x = event.GetX()
        self.y = event.GetY()
        event.Skip()

    def OnRightClick(self, event):
        try:
            n = self.klist.GetItemText(self.currentItem)
            menu = wxMenu()
            forceId = wxNewId()
            clearId = wxNewId()
            removeTabId = wxNewId()
            menu.Append(forceId, "Download Selected")
            menu.Append(clearId, "Clear All Keys")
            menu.Append(removeTabId, "Remove this Search Tab")
            EVT_MENU(self, clearId, self.EvtClearAll)
            EVT_MENU(self, forceId, self.ForceDownload)
            EVT_MENU(self, removeTabId, self.RemoveTab)
            self.PopupMenu(menu, wxPoint(self.x, self.y))
            menu.Destroy()
            event.Skip()
        except: #No keys in list
            self.x = event.GetX()
            self.y = event.GetY()
            menu = wxMenu()
            removeTabId = wxNewId()
            menu.Append(removeTabId, "Remove this Search Tab")
            EVT_MENU(self, removeTabId, self.RemoveTab)
            self.PopupMenu(menu, wxPoint(self.x, self.y))
            menu.Destroy()
            event.Skip()

    def ForceDownload(self, event):
        # Does same thing as double click, this is from OnRightClick
        nbrSelected = self.klist.GetSelectedItemCount()
        if nbrSelected == 1:
            n = self.klist.GetItemText(self.currentItem)
            self.downloadTab.AddKeyToRow(n, 'Queued') # Send it to the download tab to be queued
            #Make the key blue so we know its been sent to download
            item = self.klist.GetItem(self.currentItem)
            item.SetTextColour(wxBLUE)
            self.klist.SetItem(item)
        # Multiple selected
        else:
            totalItems = self.klist.GetItemCount()
            inc = 0
            while inc < totalItems:
                state = self.klist.GetItemState(inc, wxLIST_STATE_SELECTED)
                if state == 4: # Selected
                    n = self.klist.GetItemText(inc)
                    self.downloadTab.AddKeyToRow(n, 'Queued') # Send it to the download tab to be queued
                    #Make the key blue so we know its been sent to download
                    item = self.klist.GetItem(inc)
                    item.SetTextColour(wxBLUE)
                    self.klist.SetItem(item)
                inc = inc + 1

    def OnDoubleClick(self, event):
        n = self.klist.GetItemText(self.currentItem)
        self.downloadTab.AddKeyToRow(n, 'Queued') # Send it to the Download tab to be queued
        #Make the key blue so we know its been sent to download
        item = self.klist.GetItem(self.currentItem)
        item.SetTextColour(wxBLUE)
        self.klist.SetItem(item)
        row = self.currentItem + 1
        self.klist.SetItemState(row, wxLIST_STATE_FOCUSED, wxLIST_STATE_FOCUSED)

    def EvtClearAll(self, event):
        self.klist.DeleteAllItems()

    def ListRefresh(self):
        self.klist.Refresh()

    def AddRedRow(self, msg):
        self.klist.InsertStringItem(0, msg)
        item = self.klist.GetItem(0)
        item.SetTextColour(wxRED)
        self.klist.SetItem(item)
        self.ListRefresh()
