# -*- coding: utf-8 -*-

# Copyright (C) 2004-2007 Johan Svedberg <johan@svedberg.com>

# This file is part of ontv.

# ontv 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.

# ontv 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 General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with ontv; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA

from gettext import gettext as _

import gtk
import gobject

import GUI
from GUI import ProgramContextMenu
from ProgramDialog import ProgramDialog
from Reminders import Reminder
from ontv import NAME

TIMEOUT = 100

class SearchDialog:
    def __init__(self, xmltvfile, reminders):
        xmltvfile.connect("loading-done", self.__xmltvfile_loading_done)
        self.reminders = reminders

        self.__get_widgets()
        self.__make_channels_combobox()
        self.__make_search_treeview()
        self.__connect_widgets()

        self.search_label.set_mnemonic_widget(self.search_entry)

        self.__timeout_id = 0

    def __get_widgets(self):
        xml = gtk.glade.XML(GUI.glade_file, domain=NAME.lower())

        self.dialog = xml.get_widget("search_dialog")
        self.close_button = xml.get_widget("search_closebutton")
        self.details_button = xml.get_widget("details_button")

        self.search_label = xml.get_widget("search_label")
        self.search_entry = xml.get_widget("search_entry")
        self.channels_combobox = xml.get_widget("channels_combobox")

        self.search_treeview = xml.get_widget("search_treeview")

    def __make_channels_combobox(self):
        crt = gtk.CellRendererText()
        self.channels_combobox.pack_start(crt, True)
        self.channels_combobox.add_attribute(crt, 'text', 0)

    def __make_search_treeview(self):
        search_model = gtk.ListStore(object)
        self.search_treeview.set_model(search_model)

        crt = gtk.CellRendererText()
        crt.props.xpad = 3
        crt.props.ypad = 3
        time_column = gtk.TreeViewColumn("Air time", crt)
        time_column.set_cell_data_func(crt, self.__crt_cell_data_func)
        self.search_treeview.append_column(time_column)

        crtext = gtk.CellRendererText()
        crtext.props.xpad = 3
        crtext.props.ypad = 3
        program_column = gtk.TreeViewColumn("Program", crtext)
        program_column.set_cell_data_func(crtext, self.__crtext_cell_data_func)
        self.search_treeview.append_column(program_column)

    def __crt_cell_data_func(self, column, cell, model, iter):
        program = model.get_value(iter, 0)
        markup = "<b>%s-%s</b>\n<i>%s</i>"
        cell.props.markup = markup % (program.start_time, program.stop_time,
                                      program.date)

    def __crtext_cell_data_func(self, column, cell, model, iter):
        program = model.get_value(iter, 0)
        markup = "<b>%s</b>\n<i>%s</i>"
        cell.props.markup = markup % (program.markup_escaped_title,
                                      program.channel.markup_escaped_name)

    def __connect_widgets(self):
        self.dialog.connect("delete-event", self.__dialog_delete)

        self.search_entry.connect("changed", self.__search_entry_changed)

        selection = self.search_treeview.get_selection()
        selection.connect("changed", self.__search_treeview_selection_changed)
        self.search_treeview.connect("row-activated",
                                     self.__search_treeview_row_activated)

        self.close_button.connect("clicked", self.__close_button_clicked)
        self.details_button.connect("clicked", self.__details_button_clicked)

    def __dialog_delete(self, dialog, event):
        self.dialog.hide()
        return True

    def __search_entry_changed(self, entry):
        if self.__timeout_id > 0:
            gobject.source_remove(self.__timeout_id)

        self.__timeout_id = gobject.timeout_add(TIMEOUT, self.__search)

    def __search(self):
        search_model = self.search_treeview.get_model()
        search_model.clear()
        program_column = self.search_treeview.get_column(1)
        search = self.search_entry.get_text().strip().lower().split()
        active = self.channels_combobox.get_active()
        channels_model = self.channels_combobox.get_model()
        channel = channels_model[active][0]

        if len(search) > 0:
            matches = self.listings.search_program(search, channel)
            iter = search_model.get_iter_first()
            for row in search_model:
                program = row[0]
                if not program in matches:
                    search_model.remove(iter)
                else:
                    matches.remove(program)
                    search_model.iter_next(iter)

            for program in matches:
                search_model.append([program])
                program_column.queue_resize()

        program_column.queue_resize()
        self.search_treeview.set_cursor(0)
        return False

    def __search_treeview_selection_changed(self, selection):
        (search_model, search_iter) = selection.get_selected()
        if search_iter:
            self.details_button.set_sensitive(True)
            program = search_model.get_value(search_iter, 0)
            reminder = Reminder(program.title,
                                program.channel.markup_escaped_name)
            if not reminder in self.reminders.reminders:
                self.search_treeview_menu.add_reminder_imi.set_sensitive(True)
            else:
                self.search_treeview_menu.add_reminder_imi.set_sensitive(False)
        else:
            self.details_button.set_sensitive(False)
            self.search_treeview_menu.add_reminder_imi.set_sensitive(False)

    def __search_treeview_row_activated(self, treeview, path, column):
        self.details_button.emit("clicked")

    def __search_treeview_button_press(self, treeview, event, menu):
        if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
            search_model = treeview.get_model()
            path = treeview.get_path_at_pos(int(event.x), int(event.y))[0]
            program = search_model[path][0]
            if program.description and program.description != "":
                self.search_treeview_menu.details_imi.set_sensitive(True)
            else:
                self.search_treeview_menu.details_imi.set_sensitive(False)

            menu.popup(None, None, None, event.button, event.time)

    def __close_button_clicked(self, button):
        self.dialog.hide()

    def __details_button_clicked(self, button):
        program = GUI.get_selected_value(self.search_treeview)
        self.__show_program_dialog(program)

    def __show_program_dialog(self, program):
        pd = ProgramDialog(program)
        pd.show()

    def __xmltvfile_loading_done(self, xmltvfile, listings):
        if listings:
            self.listings = listings
            self.search_entry.emit("changed")

    def set_all_as_combo_active(self, combobox):
        channels_model = combobox.get_model()
        channels_iter = channels_model.get_iter_first()
        for row in channels_model:
            if row[0] == _("All"):
                combobox.set_active_iter(channels_iter)
                break
            channels_iter = channels_model.iter_next(channels_iter)

    def create_search_treeview_menu(self, reminders_model):
        self.search_treeview_menu = ProgramContextMenu(self.get_program,
                                                       self.reminders,
                                                       reminders_model)
        self.search_treeview.connect("button-press-event",
                                     self.__search_treeview_button_press,
                                     self.search_treeview_menu)

    def get_program(self):
        return GUI.get_selected_value(self.search_treeview)

    def show(self, uicomponent=None, verb=None):
        self.present()

    def present(self, time=None):
        self.search_treeview.set_cursor(0)
        self.search_entry.grab_focus()
        self.dialog.grab_focus()
        if time:
            self.dialog.present_with_time(time)
            # Ugly, but the only way I could get it to work correct
            self.dialog.present_with_time(time)
        else:
            self.dialog.present()

# vim: set sw=4 et sts=4 tw=79 fo+=l:
