#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Author: Ingelrest François (Athropos@gmail.com)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

import consts, dlgAbout, dlgOutput, gettext, gtk, gtk.glade, locale, os.path, prefsManager, sys, treeview


#==========================================================
#
# Functions
#
#==========================================================

def getAdvancedSettings(includeCreationSettings) :
    """ 
        Create a list with all advanced settings
        Return an empty list if advanced settings are not used
    """
    if not prefsManager.get('chkUseAdvSettings') :
        return []

    list = ['-m' + str(prefsManager.get('spnMemoryUsage'))]
    if includeCreationSettings :
        # Blocks
        if prefsManager.get('grpBlocks') == 'radBlockCount' :
            list += ['-b' + str(prefsManager.get('spnBlockCount'))]
        elif prefsManager.get('grpBlocks') == 'radBlockSize' :
            list += ['-s' + str(prefsManager.get('spnBlockSize') * 1024)]
        # Redundancy
        if prefsManager.get('grpRedundancy') == 'radRedundancyLvl' :
            list += ['-r' + str(prefsManager.get('spnRedundancyLvl'))]
        else :
            list += ['-c' + str(prefsManager.get('spnRedundancyCount'))]
        # Parity files
        if prefsManager.get('grpParity') == 'radParityLimitSize' :
            list += ['-l']
        else :
            list += ['-n' + str(prefsManager.get('spnRecoveryCount'))]
            if prefsManager.get('chkUniformFileSize') :
                list += ['-u']
        # Beginning
        list += ['-f' + str(prefsManager.get('spnFirstBlock'))]
    return list


def prefsToWidgets() :
    """
        Transfer the preferences to the widgets 
    """
    map(lambda nbkName : wTree.get_widget(nbkName).set_current_page(prefsManager.get(nbkName)), notebooks)
    map(lambda spnName : wTree.get_widget(spnName).set_value(prefsManager.get(spnName)), spinButtons)
    map(lambda chkName : wTree.get_widget(chkName).set_active(prefsManager.get(chkName)), checkButtons)
    for group in radioButtons :
        wTree.get_widget(prefsManager.get(group)).set_active(True)
        onRadioButton(wTree.get_widget(prefsManager.get(group)))


#==========================================================
#
# Events handlers
#
#==========================================================

def onRadioButton(radio, data=None) :
    """
        Radio buttons
    """
    if radio.get_active() :
        prefsManager.set(radio.get_parent().get_name(), radio.get_name())
        toBeEnabled, toBeDisabled = radioActions[radio.get_name()]
        map(lambda widget : wTree.get_widget(widget).set_sensitive(True), toBeEnabled)
        map(lambda widget : wTree.get_widget(widget).set_sensitive(False), toBeDisabled)


def onCheckBox(check) :
    """
        Check boxes
    """
    prefsManager.set(check.get_name(), check.get_active())
    if check.get_name() == 'chkUseAdvSettings' :
        if check.get_active() :
            onNotebook(wTree.get_widget('nbkMain'), None, prefsManager.get('nbkMain'))
            wTree.get_widget('boxAdv').show()
        else :
            wTree.get_widget('boxAdv').hide()


def onNotebook(notebook, page, pageNum) :
    """
        Notebooks
    """
    prefsManager.set(notebook.get_name(), int(pageNum))
    if notebook.get_name() == 'nbkMain' and prefsManager.get('chkUseAdvSettings') :
        if pageNum == prefsManager.PAGE_CREATE :
            map(lambda num : wTree.get_widget('nbkAdvanced').get_nth_page(num).show(), range(1,5))
        else :
            map(lambda num : wTree.get_widget('nbkAdvanced').get_nth_page(num).hide(), range(1,5))


def onQuit(widget) :
    """
        Quit events
    """
    prefsManager.save()
    gtk.main_quit()


def onBtnDefault(button) :
    """
        "Default advanced settings" button
    """
    prefsManager.resetAdvSettings()
    prefsToWidgets()


def onBtnGo(button) :
    """
        "Go" button
    """
    import msgBox
    import dlgSavePar2
    from gettext import gettext as _

    # Repair/Verify
    if prefsManager.get('nbkMain') == prefsManager.PAGE_CHECK :
        filename = wTree.get_widget('fcOpenPar2').get_filename()
        if filename is None :
            msgBox.error(window, _('You must first select a par2 file!'))
        else :
            dlgOutput.show(window, 'par2', ['par2', checkActions[prefsManager.get('grpAction')]] + getAdvancedSettings(False) + ['--', filename])
    # Create
    else :
        selectedFiles = treeview.getAllFilenames()
        if len(selectedFiles) == 0 :
            msgBox.error(window, _('You must first add some files to protect!'))
        else :
            filename = dlgSavePar2.show(window, selectedFiles[0] + '.par2')
            if filename is not None :
                dlgOutput.show(window, 'par2', ['par2', 'c'] + getAdvancedSettings(True) + ['--', filename] + selectedFiles)

#==========================================================
#
# Entry point
#
#==========================================================

gtk.window_set_default_icon(gtk.gdk.pixbuf_new_from_file(consts.fileImgIcon))

# Localization
locale.setlocale(locale.LC_ALL, '')
gettext.textdomain(consts.appNameShort)
gettext.bindtextdomain(consts.appNameShort, consts.dirLocale)
gtk.glade.textdomain(consts.appNameShort)
gtk.glade.bindtextdomain(consts.appNameShort, consts.dirLocale)

checkActions = {'radActionRepair' : 'r', 'radActionVerify' : 'v'}

# Check whether a .par2 file was specified on the command line
if len(sys.argv) == 2 and sys.argv[1].lower().endswith('.par2') :
    dlgOutput.run('par2', ['par2', checkActions[prefsManager.get('grpAction')]] + getAdvancedSettings(False) + ['--', sys.argv[1]])
    sys.exit()

# Widgets which state is saved and restored
notebooks    = ['nbkMain', 'nbkAdvanced']
spinButtons  = ['spnMemoryUsage', 'spnBlockCount', 'spnBlockSize', 'spnRedundancyLvl', 'spnRedundancyCount', 'spnRecoveryCount', 'spnFirstBlock']
checkButtons = ['chkUseAdvSettings', 'chkUniformFileSize']
radioButtons = ['grpAction', 'grpBlocks', 'grpRedundancy', 'grpParity']
# The first list in the tuple contains the widgets that must be enabled, the second one contains the widgets that must be disabled
radioActions = {'radActionRepair'    : ([],                                         []                                        ),
                'radActionVerify'    : ([],                                         []                                        ),
                'radBlockDynamic'    : ([],                                         ['spnBlockCount', 'spnBlockSize' ]        ),
                'radBlockCount'      : (['spnBlockCount'],                          ['spnBlockSize']                          ),
                'radBlockSize'       : (['spnBlockSize'],                           ['spnBlockCount']                         ),
                'radRedundancyLvl'   : (['spnRedundancyLvl'],                       ['spnRedundancyCount']                    ),
                'radRedundancyCount' : (['spnRedundancyCount'],                     ['spnRedundancyLvl']                      ),
                'radParityLimitSize' : ([],                                         ['spnRecoveryCount', 'chkUniformFileSize']),
                'radParityCount'     : (['spnRecoveryCount', 'chkUniformFileSize'], []                                        )}

# Create the GUI
wTree  = gtk.glade.XML(os.path.join(consts.dirRes, 'win-main.glade'), domain=consts.appNameShort)
window = wTree.get_widget('win-main')
treeview.set(window, wTree.get_widget('treeview'), wTree.get_widget('lblTree'))

# Connect handlers
wTree.signal_connect('onQuit',                onQuit)
wTree.signal_connect('onBtnGo',               onBtnGo)
wTree.signal_connect('onBtnDefault',          onBtnDefault)
wTree.signal_connect('onNotebook',            onNotebook)
wTree.signal_connect('onRadioButton',         onRadioButton)
wTree.signal_connect('onCheckBox',            onCheckBox)
wTree.signal_connect('onTreeviewKey',         treeview.onKey)
wTree.signal_connect('onTreeviewMouseButton', treeview.onMouseButton)
wTree.signal_connect('onTreeviewDragDrop',    treeview.onDragDrop)
wTree.signal_connect('onMnuAbout',            lambda widget : dlgAbout.show(window))
wTree.signal_connect('onSpinButton',          lambda spin : prefsManager.set(spin.get_name(), int(spin.get_value())))

# Prepare the file chooser
filter = gtk.FileFilter()
filter.add_pattern('*.par2')
filter.add_pattern('*.PAR2')
wTree.get_widget('fcOpenPar2').set_filter(filter)
wTree.get_widget('fcOpenPar2').set_current_folder(consts.dirUsr)

# Add specified files, if any, to the tree
if len(sys.argv) > 1 :
    for path in map(os.path.abspath, sys.argv[1:]) :
        if os.path.isfile(path) :
            treeview.addFile(path)
        elif os.path.isdir(path) :
            treeview.addDirectoryContent(path)
    wTree.get_widget('nbkMain').set_current_page(prefsManager.PAGE_CREATE)

# Here we go
prefsToWidgets()
window.show()
gtk.main()
