#!/usr/local/bin/python2.7
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai

__license__   = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'

from PyQt4.Qt import QApplication

from calibre.gui2.preferences import ConfigWidgetBase, test_widget, \
        CommaSeparatedList
from calibre.gui2.preferences.search_ui import Ui_Form
from calibre.gui2 import config, error_dialog
from calibre.utils.config import prefs

class ConfigWidget(ConfigWidgetBase, Ui_Form):

    def genesis(self, gui):
        self.gui = gui
        db = gui.library_view.model().db
        self.db = db

        r = self.register

        r('search_as_you_type', config)
        r('highlight_search_matches', config)
        r('limit_search_columns', prefs)
        r('limit_search_columns_to', prefs, setting=CommaSeparatedList)
        fl = db.field_metadata.get_search_terms()
        self.opt_limit_search_columns_to.update_items_cache(fl)
        self.clear_history_button.clicked.connect(self.clear_histories)

        self.gst_explanation.setText('<p>' + _(
    "<b>Grouped search terms</b> are search names that permit a query to automatically "
    "search across more than one column. For example, if you create a grouped "
    "search term <code>allseries</code> with the value "
    "<code>series, #myseries, #myseries2</code>, then "
    "the query <code>allseries:adhoc</code> will find 'adhoc' in any of the "
    "columns <code>series</code>, <code>#myseries</code>, and "
    "<code>#myseries2</code>.<p> Enter the name of the "
    "grouped search term in the drop-down box, enter the list of columns "
    "to search in the value box, then push the Save button. "
    "<p>Note: Search terms are forced to lower case; <code>MySearch</code> "
    "and <code>mysearch</code> are the same term."
    "<p>You can have your grouped search term show up as user categories in "
    " the Tag Browser. Just add the grouped search term names to the Make user "
    "categories from box. You can add multiple terms separated by commas. "
    "The new user category will be automatically "
    "populated with all the items in the categories included in the grouped "
    "search term. <p>Automatic user categories permit you to see easily "
    "all the category items that "
    "are in the columns contained in the grouped search term. Using the above "
    "<code>allseries</code> example, the automatically-generated user category "
    "will contain all the series mentioned in <code>series</code>, "
    "<code>#myseries</code>, and <code>#myseries2</code>. This "
    "can be useful to check for duplicates, to find which column contains "
    "a particular item, or to have hierarchical categories (categories "
    "that contain categories)."))
        self.gst = db.prefs.get('grouped_search_terms', {})
        self.orig_gst_keys = self.gst.keys()

        fl = []
        for f in db.all_field_keys():
            fm = db.metadata_for_field(f)
            if not fm['search_terms']:
                continue
            if not fm['is_category']:
                continue
            fl.append(f)
        self.gst_value.update_items_cache(fl)
        self.fill_gst_box(select=None)

        self.gst_delete_button.setEnabled(False)
        self.gst_save_button.setEnabled(False)
        self.gst_names.currentIndexChanged[int].connect(self.gst_index_changed)
        self.gst_names.editTextChanged.connect(self.gst_text_changed)
        self.gst_value.textChanged.connect(self.gst_text_changed)
        self.gst_save_button.clicked.connect(self.gst_save_clicked)
        self.gst_delete_button.clicked.connect(self.gst_delete_clicked)
        self.gst_changed = False

        if db.prefs.get('grouped_search_make_user_categories', None) is None:
            db.prefs.set('grouped_search_make_user_categories', [])
        r('grouped_search_make_user_categories', db.prefs, setting=CommaSeparatedList)
        self.muc_changed = False
        self.opt_grouped_search_make_user_categories.editingFinished.connect(
                                                        self.muc_box_changed)

    def muc_box_changed(self):
        self.muc_changed = True

    def gst_save_clicked(self):
        idx = self.gst_names.currentIndex()
        name = icu_lower(unicode(self.gst_names.currentText()))
        if not name:
            return error_dialog(self.gui, _('Grouped Search Terms'),
                                _('The search term cannot be blank'),
                                show=True)
        if idx != 0:
            orig_name = unicode(self.gst_names.itemData(idx).toString())
        else:
            orig_name = ''
        if name != orig_name:
            if name in self.db.field_metadata.get_search_terms() and \
                    name not in self.orig_gst_keys:
                return error_dialog(self.gui, _('Grouped Search Terms'),
                    _('That name is already used for a column or grouped search term'),
                    show=True)
            if name in [icu_lower(p) for p in self.db.prefs.get('user_categories', {})]:
                return error_dialog(self.gui, _('Grouped Search Terms'),
                    _('That name is already used for user category'),
                    show=True)

        val = [v.strip() for v in unicode(self.gst_value.text()).split(',') if v.strip()]
        if not val:
            return error_dialog(self.gui, _('Grouped Search Terms'),
                _('The value box cannot be empty'), show=True)

        if orig_name and name != orig_name:
            del self.gst[orig_name]
        self.gst_changed = True
        self.gst[name] = val
        self.fill_gst_box(select=name)
        self.changed_signal.emit()

    def gst_delete_clicked(self):
        if self.gst_names.currentIndex() == 0:
            return error_dialog(self.gui, _('Grouped Search Terms'),
                _('The empty grouped search term cannot be deleted'), show=True)
        name = unicode(self.gst_names.currentText())
        if name in self.gst:
            del self.gst[name]
            self.fill_gst_box(select='')
            self.changed_signal.emit()
            self.gst_changed = True

    def fill_gst_box(self, select=None):
        terms = sorted(self.gst.keys())
        self.opt_grouped_search_make_user_categories.update_items_cache(terms)
        self.gst_names.blockSignals(True)
        self.gst_names.clear()
        self.gst_names.addItem('', '')
        for t in terms:
            self.gst_names.addItem(t, t)
        self.gst_names.blockSignals(False)
        if select is not None:
            if select == '':
                self.gst_index_changed(0)
            elif select in terms:
                self.gst_names.setCurrentIndex(self.gst_names.findText(select))

    def gst_text_changed(self):
        self.gst_delete_button.setEnabled(False)
        self.gst_save_button.setEnabled(True)

    def gst_index_changed(self, idx):
        self.gst_delete_button.setEnabled(idx != 0)
        self.gst_save_button.setEnabled(False)
        self.gst_value.blockSignals(True)
        if idx == 0:
            self.gst_value.setText('')
        else:
            name = unicode(self.gst_names.itemData(idx).toString())
            self.gst_value.setText(','.join(self.gst[name]))
        self.gst_value.blockSignals(False)

    def commit(self):
        if self.gst_changed:
            self.db.prefs.set('grouped_search_terms', self.gst)
            self.db.field_metadata.add_grouped_search_terms(self.gst)
        return ConfigWidgetBase.commit(self)

    def refresh_gui(self, gui):
        gui.set_highlight_only_button_icon()
        if self.muc_changed:
            gui.tags_view.recount()
        gui.search.search_as_you_type(config['search_as_you_type'])
        gui.search.do_search()

    def clear_histories(self, *args):
        for key, val in config.defaults.iteritems():
            if key.endswith('_search_history') and isinstance(val, list):
                config[key] = []
        self.gui.search.clear_history()

if __name__ == '__main__':
    app = QApplication([])
    test_widget('Interface', 'Search')

