__author__ = 'laharah'


import gtk
import os
import time
import webbrowser

from twisted.internet import defer

from deluge.ui.client import client
import deluge.component as component

from filebottool.common import get_resource
from filebottool.common import LOG
from filebottool.gtkui.common import EditableList
from filebottool.gtkui.handler_editor import HandlerEditor
import filebottool.auto_sort

import user_messenger

SORT_OPERATORS = filebottool.auto_sort.OPERATOR_MAP.keys()
VALID_FIELDS = filebottool.auto_sort.VALID_FIELDS

FilterRule = filebottool.auto_sort.FilterRule

log = LOG


class ConfigUI(object):
    """handles the UI portion of getting and setting preferences"""

    def __init__(self, settings=None):
        self.glade = gtk.glade.XML(get_resource("config.glade"))
        self.config_page = self.glade.get_widget("prefs_box")
        self.pref_dialog = component.get("Preferences").pref_dialog

        fb_icon = self.glade.get_widget("fb_icon")
        image = get_resource("fb_icon16.png")
        fb_icon.set_from_file(image)

        model = gtk.ListStore(str)
        view = self.glade.get_widget('saved_handlers_listview')
        renderer = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Profile Name", renderer, text=0)
        view.append_column(column)
        model.set_sort_column_id(0, gtk.SORT_ASCENDING)
        self.handlers_list = EditableList(view, model)

        model = gtk.ListStore(str, str, str, str)
        view = self.glade.get_widget('rule_listview')
        options = [
            ("Field:", VALID_FIELDS),
            ("Comparison Operator:", SORT_OPERATORS),
        ]
        for col_index, tup in enumerate(options):
            name, items = tup
            combo_model = gtk.ListStore(str)
            for item in items:
                combo_model.append([item])
            cb = build_combo_renderer_cb(model, col_index, items)
            renderer = build_combo_cellrenderer(combo_model, cb)
            column = gtk.TreeViewColumn(name, renderer, text=col_index)
            view.append_column(column)
        renderer = gtk.CellRendererText()
        renderer.set_property("editable", True)
        def text_edited(widget, path, text):
            model[path][2] = text
        renderer.connect("edited", text_edited)
        column = gtk.TreeViewColumn("Pattern to Match:", renderer, text=2)
        view.append_column(column)
        self.rules_list = EditableList(view, model)

        self.glade.signal_autoconnect({
            "on_add_handler": self.on_add_handler,
            "on_remove_handler": self.handlers_list.remove,
            "on_edit_handler": self.on_edit_handler,
            "on_move_rule_up": self.rules_list.move_up,
            "on_move_rule_down": self.rules_list.move_down,
            "on_remove_rule": self.rules_list.remove,
            "on_add_rule": self.on_add_rule,
            "on_auto_sort_help_clicked": self.on_auto_sort_help_clicked,
            "on_debug_button_clicked": self.on_debug_button_clicked,
            "on_license_button_clicked": self.on_license_button_clicked,
        })
        self.gather_time = None
        if settings:
            self.populate_settings(settings)

    def populate_settings(self, settings):
        """populates the UI widgets with the given settings"""
        # workaround for new settings being overwritten by previous settings
        if self.gather_time:
            if time.time() - self.gather_time < 1:
                return

        self.config = settings
        self.saved_handlers = settings["saved_handlers"]
        self.handlers_list.clear()
        for name in self.saved_handlers:
            self.handlers_list.add([name])

        rules = settings["auto_sort_rules"]
        if len(self.rules_list.view.get_columns()) == 4:  # force refresh
            self.rules_list.view.remove_column(self.rules_list.view.get_column(3))
        self.rule_handler_combo = build_combo_cellrenderer(
            self.handlers_list.model, self.on_rule_handler_combo_changed)
        column_name = "Profile to Use:"
        column = gtk.TreeViewColumn(column_name, self.rule_handler_combo, text=3)
        self.rules_list.view.append_column(column)
        self.rules_list.clear()
        for rule in rules:
            self.rules_list.add(rule[1:])
        for column in self.rules_list.view.get_columns():
            column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
            column.set_resizable(True)

        if not rules:
            for column in self.rules_list.view.get_columns():
                column.set_expand(True)

    def gather_settings(self):
        """
        Updates the given config dictionary and updates the appropriate
        settings.
        """
        self.gather_time = time.time()
        handlers = {}
        for row in self.handlers_list.get_data():
            handlers[row[0]] = self.saved_handlers[row[0]]
        self.saved_handlers = handlers
        self.config["saved_handlers"] = self.saved_handlers

        rules = []
        log.debug(self.rules_list.get_data())
        for index, row in enumerate(self.rules_list.get_data()):
            field, op, pat, handler = row
            rules.append([index, field, op, pat, handler])

        self.config['auto_sort_rules'] = rules
        return self.config

#########
#  Section: signal handlers
#########

    def on_add_handler(self, widget):
        def new_handler_cb(id, handlers):
            self.handlers_list.add([id])
            self.saved_handlers = handlers
            log.debug(self.saved_handlers)

        HandlerEditor(handlers=self.saved_handlers, cb=new_handler_cb,
                      parent=self.pref_dialog)

    def on_edit_handler(self, widget):
        handler_name = self.handlers_list.get_row()[0]
        def edited_cb(id, handlers):
            self.saved_handlers = handlers
            if id != handler_name:
                del self.saved_handlers[handler_name]
                self.handlers_list.clear()
                for name in self.saved_handlers:
                    self.handlers_list.add([name])

        HandlerEditor(handlers=self.saved_handlers, initial=handler_name,
                      cb=edited_cb, parent=self.pref_dialog)


    def on_add_rule(self, *args):
        self.rules_list.add(['', "is exactly", '', ''])
        path = self.rules_list.model.get_string_from_iter(self.rules_list.model[-1].iter)
        self.rules_list.view.set_cursor(path)

    def on_rule_handler_combo_changed(self, widget, path, text):
        self.rules_list.model[path][3] = text

    def on_auto_sort_help_clicked(self, *args):
        webbrowser.open('https://github.com/Laharah/deluge-FileBotTool/wiki/Auto-Sorting',
                        new=2)

    @defer.inlineCallbacks
    def on_debug_button_clicked(self, button):
        log.debug("Sending request for FileBot debug info...")
        button.set_sensitive(False)
        info = yield client.filebottool.get_filebot_debug()
        log.debug("Displaying debug info")
        dialog = user_messenger.UserMessenger()
        dialog.display_text("Filebot Debug Info", info)
        button.set_sensitive(True)

    @defer.inlineCallbacks
    def on_license_button_clicked(self, button):
        log.debug("License button clicked.")
        chooser = gtk.FileChooserDialog(_("Choose your FileBot license file"),
            None,
            gtk.FILE_CHOOSER_ACTION_OPEN,
            buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN,
                        gtk.RESPONSE_OK))

        chooser.set_transient_for(self.pref_dialog)
        chooser.set_property("skip-taskbar-hint", True)
        chooser.set_local_only(False)

        file_filter = gtk.FileFilter()
        file_filter.set_name(_("FileBot license files"))
        file_filter.add_pattern("*." + "psm")
        chooser.add_filter(file_filter)
        file_filter = gtk.FileFilter()
        file_filter.set_name(_("All files"))
        file_filter.add_pattern("*")
        chooser.add_filter(file_filter)

        # Run the dialog
        response = chooser.run()

        if response == gtk.RESPONSE_OK:
            license = chooser.get_filenames()[0]
        else:
            chooser.destroy()
            return
        chooser.destroy()

        # License file should definetly be under 10K
        size = os.stat(license).st_size
        if size > 10*1000:
            e = user_messenger.InfoDialog("Error", "License file is too big.")
            e.resize(220, 125)
            e.run_async()
            defer.returnValue()

        with open(license, 'rb') as l:
            license_data = l.read()
        log.debug("Sending license data to server.")
        result = yield client.filebottool.activate_filebot_license(license_data)
        log.debug("Recieved reply from server: %s", result)
        if result.startswith("FilebotLicenseError: "):
            title = "Error with License File"
            msg = result[21:]
        else:
            title = "Success!"
            msg = result

        dialog = user_messenger.InfoDialog(title, msg)
        dialog.resize(220, 125)
        dialog.run_async()




#########
#  Section: Utilities
#########

def build_combo_renderer_cb(list_store, column_number, allowed=None):
    def cb(widget, path, text):
        if allowed:
            if text not in allowed:
                return
        log.debug('{0} {1} {2}'.format(widget, path, text))
        list_store[path][column_number] = text
    return cb

def build_combo_cellrenderer(model, cb):
    renderer = gtk.CellRendererCombo()
    if model:
        renderer.set_property("model", model)
    renderer.set_property("editable", True)
    renderer.set_property("text-column", 0)
    renderer.connect("edited", cb)
    return renderer