
import wx
import wx.xrc as xrc
import  listctrl  as  listmix
from gui import images
import gui.tree
from ipodder.contrib import feedparser
import platform
import os.path
from  localization import LanguageModule

# Skinning
from gui.skin import STRIPE_EVEN_COLOR, STRIPE_ODD_COLOR

class AutoWidthListCtrl(wx.ListCtrl,listmix.ListCtrlAutoWidthMixin):
    def __init__(self):
        p = wx.PreListCtrl()
        self.PostCreate(p)
        listmix.ListCtrlAutoWidthMixin.__init__(self)

class MainPanel(wx.Panel, listmix.ColumnSorterMixin):
    def __init__(self):
        p = wx.PrePanel()
        self.PostCreate(p)
        self.initialized = False
        
    def InitSortMixin(self,list,sm_up,sm_dn):
        self.initialized = True
        self.list = list
        self.sm_up = sm_up
        self.sm_dn = sm_dn
        self.ResetSortMixin()
        listmix.ColumnSorterMixin.__init__(self, 4)
        #Re-assign this method so we can re-stripe after a sort.
        self.list.SortItems = self.SortItems
       
    def ResetSortMixin(self):
        if not self.initialized:
            return
        self.itemDataMap = {}
        for n in range(self.list.GetItemCount()):
            mb = self.list.GetItem(n,2).GetText()
            if mb == "":
                mbstring = "0.0"
            else:
                mbstring = mb
            self.itemDataMap[self.list.GetItemData(n)] = (
                self.list.GetItem(n,0).GetText(),
                self.list.GetItem(n,1).GetText(),
                float(mbstring),
                self.list.GetItem(n,3).GetText()
            )
        if hasattr(self,"_col"):
            self.GetListCtrl().SortItems(self.GetColumnSorter())
        
    def GetListCtrl(self):
        return self.list

    #Supports re-striping
    def SortItems(self,columnSorter):
        wx.ListCtrl.SortItems(self.list,columnSorter)
        for i in range(self.list.GetItemCount()):
            if i % 2 == 0:
                self.list.SetItemBackgroundColour(i,STRIPE_ODD_COLOR)
            else:
                self.list.SetItemBackgroundColour(i,STRIPE_EVEN_COLOR)

    #Slight variation on the library version: bash col 0 to lowercase first.
    def __MyColumnSorter(self, key1, key2):
        col = self._col
        ascending = self._colSortFlag[col]
        item1 = self.itemDataMap[key1][col]
        item2 = self.itemDataMap[key2][col]

        if col == 0:
            item1 = item1.lower()
            item2 = item2.lower()

        #i18n stuff crashes on mac
	cmpVal = cmp(item1, item2)

        # If the items are equal then pick something else to make the sort value unique
        if cmpVal == 0:
            cmpVal = apply(cmp, self.GetSecondarySortValues(col, key1, key2))

        if ascending:
            return cmpVal
        else:
            return -cmpVal
    
    def GetColumnSorter(self):
        return self.__MyColumnSorter

    # Used by the ColumnSorterMixin, see wxPython/lib/mixins/listctrl.py
    def GetSortImages(self):
        return (self.sm_dn, self.sm_up)

    def GetState(self):
        return (self._col,self._colSortFlag[self._col])

    def SetState(self,state):
        self._col = state[0]
        self._colSortFlag[state[0]] = state[1]
        self.SortListItems()

class FeedWindow(wx.Dialog):
    def __init__(self):
        p = wx.PreDialog()
        self.PostCreate(p)
        wx.EVT_BUTTON(self, xrc.XRCID("FEEDWINCANCEL"),self.OnCancel)
        wx.EVT_BUTTON(self, xrc.XRCID("FEEDWINOK"),self.OnSaveSettings)
        self.initialized = False
        self.feedinfo = None
        self.parent = None

    def _(self,key):
        return self.m_stringtable.GetText(self.m_currentlanguage,key)
        
    def ValueControl(self, id, label):
        xrc.XRCCTRL(self, id).SetLabel(self._(label))
                
    def SetLanguages(self):
        self.ValueControl("FEEWDINCANCEL", "str_cancel")
        self.ValueControl("FEEDWINOK", "str_ok")
                        
    def Init(self, ipodder):
        self.ipodder = ipodder
        self.feedwintitle = xrc.XRCCTRL(self,"FEEDWINTITLE")
        self.feedwinurl = xrc.XRCCTRL(self,"FEEDWINURL")
        self.feedwingotosubs = xrc.XRCCTRL(self,"FEEDWINGOTOSUBS")
        self.initialized = True
        self.m_currentlanguage = self.ipodder.config.screen_language
        self.m_stringtable = LanguageModule.StringTable(self.m_currentlanguage)        

    def SetParent(self,parent):
        self.parent = parent

    def OnCancel(self, event):
        self.feedinfo = None
        self.Show(0)

    def UpdateFeed(self,feedinfo,ipodder,newfeed=None):
        if not self.initialized:
            self.Init(ipodder)
        if feedinfo:
            self.SetLabel(self._("str_edit_feed"))
            self.feedinfo = feedinfo
            self.feedwinurl.SetValue(feedinfo.url)
            self.feedwintitle.SetValue(feedinfo.title)
        else:
            self.feedinfo = None
            self.SetLabel(self._("str_add_feed_dialog"))
            self.feedwinurl.SetValue(newfeed)
            self.feedwintitle.SetValue("")
        self.feedwingotosubs.Enable(not self.parent.IsSubscriptionsTabSelected())
        self.GetSizer().Fit(self)
        self.feedwintitle.SetEditable(False) #temporary
        self.feedwintitle.Enable(False) #temporary
        self.ShowModal()

    def OnSaveSettings(self,event):
        url = self.feedwinurl.GetValue().strip()
        title = self.feedwintitle.GetValue().strip()
        if self.feedinfo and ['disabled','unsubscribed'].count(self.feedinfo.sub_state) == 0:
            self.feedinfo.url = url
            self.parent.UpdateFeedsListItem(self.feedinfo)
            self.parent.RefreshFeedWindowData(self.feedinfo)
        else:
            self.parent.AddFeed(url,title=url,raise_tab=self.feedwingotosubs.IsChecked())            
        self.Show(0)

class PrefsDialog(wx.Dialog):
    def __init__(self):
        p = wx.PreDialog()
        self.PostCreate(p)

    def _(self,key):
        return self.m_stringtable.GetText(self.m_currentlanguage,key)
        
    def ValueControl(self, id, label):
        xrc.XRCCTRL(self, id).SetLabel(self._(label))
        
        
    def SetLanguages(self):
        GENERAL = 0
        THREADS = 1
        NETWORKING = 2
        PLAYER = 3
        ADVANCED = 4
        
        self.SetLabel(self._("str_preferences"))
        
        tabsdict = {
            GENERAL : "str_general",
            THREADS : "str_threads",
            NETWORKING : "str_networking",
            PLAYER : "str_player",
            ADVANCED : "str_advanced"
        }
        en_loaded = False
        for key in tabsdict.keys():
            try:
                self.notebook.SetPageText(key, self._(tabsdict[key]))
            except AssertionError:
                """Unfortunately wide characters and Notebooks don't mix well
                on Mac, so we fall back to English."""
                if not en_loaded:
                    self.m_stringtable.LoadLanguage(LanguageModule.ENGLISH)
                    en_loaded = True
                self.notebook.SetPageText(key,self.m_stringtable.GetText(LanguageModule.ENGLISH,tabsdict[key]))

        self.ValueControl("PRF_LBL_GEN_OPTIONS", "str_gen_options_expl")
        self.ValueControl("HIDE_ON_STARTUP", "str_hide_on_startup")
        self.ValueControl("SCAN_ON_STARTUP", "str_run_check_startup")
        self.ValueControl("PLAY_ON_DOWNLOAD", "str_play_after_download")
        self.ValueControl("PRF_PLAYER", "str_choose_a_player")
        self.ValueControl("PRF_LBL_STORAGE_LOC_STORAGE", "str_location_and_storage")
        self.ValueControl("PRF_LBL_STORAGE_STOP", "str_stop_downloading")
        self.ValueControl("PRF_LBL_DOWNLOAD_FOLDER", "str_download_folder")
        self.ValueControl("PREFSBROWSE", "str_browse")
        
        self.ValueControl("PRF_MULTIPLE_DOWNLOAD", "str_multiple_download")
        self.ValueControl("PRF_MAX_FEEDSCANS", "str_max_feedscans")
        self.ValueControl("PRF_MAX_DOWNLOADS", "str_max_downloads")

        self.ValueControl("PRFCORALIZING", "str_coralize_urls")
        self.ValueControl("PRFUSEPROXY", "str_proxy_server")
        self.ValueControl("PRF_PROXY_ADDRESS", "str_proxy_address")
        self.ValueControl("PRF_PROXY_PORT", "str_proxy_port")

        self.ValueControl("PRF_POWER_USER", "str_options_power_users")
        self.ValueControl("DLCOMMANDENABLE", "str_run_command_download")
        self.ValueControl("PRF_RCMD_FULL_PATH", "str_rcmd_full_path")
        self.ValueControl("PRF_RCMD_PODCAST_NAME", "str_rcmd_podcast_name")

        self.ValueControl("PRF_OTHER_ADV_OPTION", "str_other_advanced_options")
        self.ValueControl("SHOWLOGPAGE", "str_show_log")

        self.ValueControl("PREFSSAVE", "str_save")
        self.ValueControl("PREFSCANCEL", "str_cancel")
        

        #"No player"
        self.playerbox.SetItemLabel(2,self.m_stringtable.GetText(self.m_currentlanguage,"str_no_player"))
        
    def OnEnableProxy(self, event):
        if self.enableProxy.IsChecked()==True:
            self.proxyPort.Enable(True)
            self.proxyHost.Enable(True)
        else:
            self.proxyPort.Enable(False)
            self.proxyHost.Enable(False)
        self.OnPrefChange(event)
    
    def Init(self,ipodder,gui):
        self.ipodder = ipodder
        self.gui = gui
        self.m_currentlanguage = self.ipodder.config.screen_language
        self.m_stringtable = LanguageModule.StringTable(self.m_currentlanguage)

        self.player_types = ["iTunes", "WindowsMedia", "NoPlayer"]
        self.notebook = xrc.XRCCTRL(self, "NOTEBOOK")
        self.hideOnStartup = xrc.XRCCTRL(self, "HIDE_ON_STARTUP")
        self.scanOnStartup = xrc.XRCCTRL(self, "SCAN_ON_STARTUP")
        self.playOnDownload = xrc.XRCCTRL(self, "PLAY_ON_DOWNLOAD")
        self.dlCommandEnable = xrc.XRCCTRL(self, "DLCOMMANDENABLE")
        self.dlCommand = xrc.XRCCTRL(self, "DLCOMMAND")
        self.showLogPage = xrc.XRCCTRL(self, "SHOWLOGPAGE")
        self.prefsSave = xrc.XRCCTRL(self, "PREFSSAVE")
        self.prefsCancel = xrc.XRCCTRL(self, "PREFSCANCEL")
        self.downloaddir = xrc.XRCCTRL(self, "PREFSDOWNLOADDIR")
        self.browse = xrc.XRCCTRL(self,"PREFSBROWSE")
        self.numFeedScanThreads = xrc.XRCCTRL(self, "NUMFEEDSCANTHREADS")
        self.numDownloadThreads = xrc.XRCCTRL(self, "NUMDOWNLOADTHREADS")
        self.maxHarddiscSizeMB = xrc.XRCCTRL(self, "MAX_HARDDISC_SIZE_MB")
        self.playerbox = xrc.XRCCTRL(self, "PRF_PLAYER")
        
        # Networking
        self.corlizeUrls = xrc.XRCCTRL(self, "PRFCORALIZING")
        self.corlizeUrls.SetValue(self.ipodder.config.coralize_urls)
        
        self.enableProxy = xrc.XRCCTRL(self, "PRFUSEPROXY")
        self.proxyHost = xrc.XRCCTRL(self, "TXTPRFPROXYHOST")
        self.proxyPort = xrc.XRCCTRL(self, "TXTPRFPROXYPORT")
                       
        self.Bind(wx.EVT_CHECKBOX, self.OnPrefChange, self.hideOnStartup)
        self.Bind(wx.EVT_CHECKBOX, self.OnPrefChange, self.scanOnStartup)
        self.Bind(wx.EVT_CHECKBOX, self.OnPrefChange, self.playOnDownload)
        self.Bind(wx.EVT_CHECKBOX, self.OnPrefChange, self.dlCommandEnable)
        self.Bind(wx.EVT_COMBOBOX, self.OnPrefChange, self.numFeedScanThreads)
        self.Bind(wx.EVT_COMBOBOX, self.OnPrefChange, self.numDownloadThreads)
        self.Bind(wx.EVT_TEXT, self.OnPrefChange, self.maxHarddiscSizeMB)
        self.Bind(wx.EVT_TEXT, self.OnPrefChange, self.dlCommand)
        self.Bind(wx.EVT_CHECKBOX, self.OnPrefChange, self.showLogPage)
        self.Bind(wx.EVT_BUTTON, self.OnPrefsSave, self.prefsSave)
        self.Bind(wx.EVT_BUTTON, self.OnPrefsCancel, self.prefsCancel)
        self.Bind(wx.EVT_TEXT, self.OnPrefChange, self.downloaddir)
        self.Bind(wx.EVT_BUTTON, self.OnPrefsBrowse, self.browse)
        self.Bind(wx.EVT_CHECKBOX, self.OnPrefChange, self.corlizeUrls)
        self.Bind(wx.EVT_RADIOBOX, self.OnPrefChange, self.playerbox)
        self.Bind(wx.EVT_CHECKBOX, self.OnEnableProxy, self.enableProxy)
        self.Bind(wx.EVT_TEXT, self.OnPrefChange, self.proxyHost)
        self.Bind(wx.EVT_TEXT, self.OnPrefChange, self.proxyPort)

        self.ResetPrefs()        
        self.SetLanguages()

        self.SetAcceleratorTable(
            wx.AcceleratorTable([(wx.ACCEL_NORMAL, wx.WXK_ESCAPE, xrc.XRCID("PREFSCANCEL"))
            ]))
            
    def ResetPrefs(self):
        self.hideOnStartup.SetValue(self.ipodder.config.hide_on_startup)
        self.scanOnStartup.SetValue(self.ipodder.config.scan_on_startup)
        self.playOnDownload.SetValue(self.ipodder.config.play_on_download)
        self.dlCommandEnable.SetValue(self.ipodder.config.dl_command_enable)
        self.dlCommand.SetValue(self.ipodder.config.dl_command)
        self.showLogPage.SetValue(self.ipodder.config.show_log_page)
        self.downloaddir.SetValue(unicode(self.ipodder.config.download_dir))
        self.corlizeUrls.SetValue(self.ipodder.config.coralize_urls)
        self.enableProxy.SetValue(self.ipodder.config.use_proxy_server)
        self.proxyPort.SetValue(self.ipodder.config.http_proxy_port)
        self.proxyHost.SetValue(self.ipodder.config.http_proxy_server)
        if self.ipodder.config.use_proxy_server is False:
            self.proxyPort.Enable(False)
            self.proxyHost.Enable(False)
        self.numFeedScanThreads.SetSelection(self.BestComboIntegerIndex(self.numFeedScanThreads,self.ipodder.config.max_scan_jobs))
        self.numDownloadThreads.SetSelection(self.BestComboIntegerIndex(self.numDownloadThreads,self.ipodder.config.max_download_jobs)) 
        self.maxHarddiscSizeMB.SetValue(str(self.ipodder.config.min_mb_free))
        self.SetPlayerBox()
        if platform.system()=='Darwin':
            #myHideButton = self.frame.FindWindowByName("ID_HIDE")
            #myHideButton.Show(False)
            self.hideOnStartup.Enable(False)
            self.playerbox.EnableItem(1,False)
        self.prefsSave.Enable(False)

    def BestComboIntegerIndex(self,combo,desired):
        """Return the index of the closest-valued integer.
        Useful when defaulting the selectlist to a possibly non-matching
        desired value."""
        idx = 0
        diff = None
        for i in range(0,combo.GetCount()):
            if diff == None or \
               abs(int(combo.GetString(i)) - desired) < diff:
                idx = i
                diff = abs(int(combo.GetString(i)) - desired)

        return idx
    
    def SetPlayerBox(self):
        player_type = self.ipodder.config.player_type
        if player_type == "iTunes":
            self.playerbox.SetSelection(0)
        elif player_type == "WindowsMedia":
            self.playerbox.SetSelection(1)
        else:
            self.playerbox.SetSelection(2)

    def OnShowLogPage(self, event):
        """Adjust the configuration and hide or show the log page."""
        if event.IsChecked(): 
            self.ipodder.config.show_log_page = True
        else: 
            self.ipodder.config.show_log_page = False
        self.ipodder.config.flush()

    def OnPrefsSave(self, event):
        #validate the download directory
        if not os.path.isdir(self.downloaddir.GetValue()):
            message1 = self._("str_bad_directory_pref_1")
            message2 = self._("str_bad_directory_pref_2")
            alert = wx.MessageDialog(self, "%s (%s).  %s" % (message1,self.downloaddir.GetValue(),message2) , style=wx.OK)
            response = alert.ShowModal()
            alert.Destroy()            
            return

        #validate the integer-valued configuration options
        try:
            int(self.maxHarddiscSizeMB.GetValue())    
        except ValueError:
            message1 = self._("str_bad_megabyte_limit_1")
            message2 = self._("str_bad_megabyte_limit_2")
            alert = wx.MessageDialog(self, "%s (%s).  %s" % (self._("str_bad_megabyte_limit_1"), self.maxHarddiscSizeMB.GetValue(), self._("str_bad_megabyte_limit_2")), style=wx.OK)
            response = alert.ShowModal()
            alert.Destroy()            
            return

        #validate the proxy settings
        if self.enableProxy.IsChecked() and (
            self.proxyHost.GetValue().strip() == '' or
            self.proxyHost.GetValue().strip() == 'http://' or
            self.proxyPort.GetValue().strip() == ''):
            alert = wx.MessageDialog(self, self._("str_bad_proxy_pref"), style=wx.OK)
            response = alert.ShowModal()
            alert.Destroy()
            return
        
        self.ipodder.config.download_dir = self.downloaddir.GetValue()
        
        self.ipodder.config.hide_on_startup = self.hideOnStartup.IsChecked()
        self.ipodder.config.scan_on_startup = self.scanOnStartup.IsChecked()
        self.ipodder.config.play_on_download = self.playOnDownload.IsChecked()
        self.ipodder.config.dl_command_enable = self.dlCommandEnable.IsChecked()
        self.ipodder.config.dl_command = self.dlCommand.GetValue()
        self.ipodder.config.show_log_page = self.showLogPage.IsChecked()            
        self.ipodder.config.max_scan_jobs = int(self.numFeedScanThreads.GetValue())
        self.ipodder.config.max_download_jobs = int(self.numDownloadThreads.GetValue())
        self.ipodder.config.min_mb_free = int(self.maxHarddiscSizeMB.GetValue())
        self.ipodder.config.coralize_urls = self.corlizeUrls.IsChecked()
        self.ipodder.config.use_proxy_server = self.enableProxy.IsChecked()
        proxyhost = self.proxyHost.GetValue()
        if "http://" not in proxyhost.lower():
            proxyhost = "http://" + proxyhost
        self.proxyHost.SetValue(proxyhost)
        self.ipodder.config.http_proxy_server = proxyhost
        self.ipodder.config.http_proxy_port =  self.proxyPort.GetValue()
        self.ipodder.config.player_type = self.player_types[self.playerbox.GetSelection()]
        self.ipodder.config.determine_player()
        self.ipodder.config.flush()
        self.gui.showlogpage(self.ipodder.config.show_log_page)
        self.ipodder.init_proxy_config()
        self.prefsSave.Enable(False)
        self.Show(0)
        
    def OnPrefChange(self, event):
        if not self.prefsSave.IsEnabled():
            self.prefsSave.Enable(True)
    
    def OnPrefsCancel(self,event):
        self.Show(0)
        self.ResetPrefs()

    def OnPrefsBrowse(self,event):
        self.OnPrefChange(event)
        dlg = wx.DirDialog(self,"Choose download directory",self.downloaddir.GetValue())
        if dlg.ShowModal() == wx.ID_OK:
            self.downloaddir.SetValue(dlg.GetPath())
        dlg.Destroy()       

