# -*- 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

import os.path
from gettext import gettext as _

import gtk
import gnomeapplet

import GUI
from Configuration import Configuration
from XMLTVFile import XMLTVFile
from Reminders import Reminders
from KeyBinder import KeyBinder
from ProgramWindow import ProgramWindow
from PreferencesDialog import PreferencesDialog
from SearchDialog import SearchDialog
from AboutDialog import AboutDialog
from XMLTVAssistant import XMLTVAssistant
from ontv import NAME, VERSION, UI_DIR, LOCALE_DIR

class OnTVApplet(object):
    """Singleton representing the applet"""

    instance = None

    def __new__(type, *args):
        if OnTVApplet.instance is None:
            OnTVApplet.instance = object.__new__(type)
            OnTVApplet.instance.__init(*args)
        return OnTVApplet.instance

    def __init(self, *args):
        self.applet = args[0]
        self.configure = args[1]
        self.config = Configuration(args[2], args[3])
        self.xmltvfile = XMLTVFile(self.config)

        self.reminders = Reminders(self.config)
        if os.path.exists(self.reminders.file):
            self.reminders = self.reminders.load()

        self.kb = KeyBinder(self.config)
        self.kb.connect("activated", self.__kb_activated)

        self.pw = ProgramWindow(self.xmltvfile, self.applet,
                                self.get_docking_data)
        self.sd = SearchDialog(self.xmltvfile, self.reminders)
        self.pd = PreferencesDialog(self)
        self.tooltips = gtk.Tooltips()

        self.applet.set_applet_flags(gnomeapplet.EXPAND_MINOR)

        ui_file = os.path.join(UI_DIR, "GNOME_OnTVApplet.xml")
        verb_list = [("Update TV listings", self.__update_listings),
                     ("Preferences", self.pd.show),
                     ("Search Program", self.sd.show),
                     ("About", self.__run_ad)]
        self.applet.setup_menu_from_file(None, ui_file, NAME, verb_list)

        self.applet.connect("button-press-event", self.__button_press)

        self.image = gtk.Image()
        if not self.config.standalone:
            size = self.applet.get_size()
            pixbuf = GUI.load_icon("ontv", size, size)
            if pixbuf.get_width() != size or pixbuf.get_height() != size:
                pixbuf = pixbuf.scale_simple(size-4, size-4,
                                             gtk.gdk.INTERP_BILINEAR)
            self.image.set_from_pixbuf(pixbuf)
        else:
            self.image.set_from_icon_name(NAME.lower(), gtk.ICON_SIZE_BUTTON)

        self.applet.add(self.image)

        self.applet.connect("change-size", self.__change_size)
        self.applet.connect("change-background", self.__change_background)

        self.applet.show_all()

    def __update_listings(self, uicomponent=None, verb=None):
        self.xmltvfile.download()

    def __run_ad(self, uicomponent=None, verb=None):
        self.ad = AboutDialog()
        self.ad.run()

    def run(self):
        if self.configure or self.config.grabber_command == '':
            assistant = XMLTVAssistant(self.config, self.xmltvfile)
            assistant.show()
        else:
            self.xmltvfile.connect("downloading", self.__xmltvfile_activity,
                                   (_("Downloading"),))
            self.xmltvfile.connect("downloading-done",
                                   self.__xmltvfile_downloading_done)
            self.xmltvfile.connect("sorting", self.__xmltvfile_activity,
                                   (_("Sorting"),))
            self.xmltvfile.connect("sorting-done",
                                   self.__xmltvfile_sorting_done)
            self.xmltvfile.connect("loading", self.__xmltvfile_activity,
                                   (_("Loading"),))
            self.xmltvfile.connect("loading-done",
                                   self.__xmltvfile_loading_done)
            # self.xmltvfile.download()
            self.xmltvfile.load()

    def __button_press(self, button, event):
        if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1:
            self.__press_button()

    def __press_button(self):
        if not self.pw.props.visible:
            self.applet.set_state(gtk.STATE_SELECTED)
            self.pw.position_window()
            self.pw.stick()
            self.pw.show_all()
            self.pw.grab_focus()
        else:
            self.applet.set_state(gtk.STATE_NORMAL)
            self.pw.hide()

        if not self.config.display_current_programs:
            self.pw.cpt.hide()
        if not self.config.display_upcoming_programs:
            self.pw.upt.hide()

    def __change_size(self, widget, size):
        pixbuf = GUI.load_icon("ontv", size, size)
        if pixbuf.get_width() != size or pixbuf.get_height() != size:
            pixbuf = pixbuf.scale_simple(size-4, size-4,
                                         gtk.gdk.INTERP_BILINEAR)
        self.image.set_from_pixbuf(pixbuf)

    def __change_background(self, widget, background, colour, pixmap):
        widgets = (self.applet, self.image)
        if background == gnomeapplet.NO_BACKGROUND or \
           background == gnomeapplet.PIXMAP_BACKGROUND:
            for widget in widgets:
                copy = widget.get_style().copy()
                copy.bg_pixmap[gtk.STATE_NORMAL] = pixmap
                copy.bg_pixmap[gtk.STATE_INSENSITIVE]  = pixmap
                widget.set_style(copy)
        elif background == gnomeapplet.COLOR_BACKGROUND:
            for widget in widgets:
                widget.modify_bg(gtk.STATE_NORMAL, colour)

    def set_tooltip(self, text):
        self.tooltips.set_tip(self.applet, text)

    def __xmltvfile_activity(self, xmltvfile, activity):
        self.set_tooltip(_("%s TV Listings...") % activity)

    def __xmltvfile_downloading_done(self, xmltvfile, pid, condition):
        self.set_tooltip(None)
        self.xmltvfile.sort()

    def __xmltvfile_sorting_done(self, xmltvfile, pid, condition):
        self.set_tooltip(None)
        self.xmltvfile.load()

    def __xmltvfile_loading_done(self, xmltvfile, listings):
        self.set_tooltip(None)

    def __kb_activated(self, kb, name, time):
        if name == "show-window-hotkey":
            self.__press_button()
        elif name == "show-search-program-hotkey":
            self.sd.present(time)

    def get_docking_data(self, middle, w=0, h=0):
        self.applet.realize()
        (x, y) = self.applet.window.get_origin()

        button_w = self.applet.allocation.width
        button_h = self.applet.allocation.height

        screen = self.applet.get_screen()

        found_monitor = False
        n = screen.get_n_monitors()
        for i in range(0, n):
            monitor = screen.get_monitor_geometry(i)
            if (x >= monitor.x and x <= monitor.x + monitor.width and
                y >= monitor.y and y <= monitor.y + monitor.height):
                    found_monitor = True
                    break

        if not found_monitor:
            screen_width = screen.get_width()
            monitor = gtk.gdk.Rectangle(0, 0, screen_width, screen_width)

        orient = self.applet.get_orient()

        if orient == gnomeapplet.ORIENT_RIGHT:
            x += button_w

            if ((y + h) > monitor.y + monitor.height):
                y -= (y + h) - (monitor.y + monitor.height)

            if middle:
                x -= button_w/2
                y += button_h/2

            if ((y + h) > (monitor.height / 2)):
                gravity = gtk.gdk.GRAVITY_SOUTH_WEST
            else:
                gravity = gtk.gdk.GRAVITY_NORTH_WEST
        elif orient == gnomeapplet.ORIENT_LEFT:
            x -= w

            if ((y + h) > monitor.y + monitor.height):
                y -= (y + h) - (monitor.y + monitor.height)

            if middle:
                x += w/2
                y += button_h/2

            if ((y + h) > (monitor.height / 2)):
                gravity = gtk.gdk.GRAVITY_SOUTH_EAST
            else:
                gravity = gtk.gdk.GRAVITY_NORTH_EAST
        elif orient == gnomeapplet.ORIENT_DOWN or self.config.standalone:
            y += button_h

            if ((x + w) > monitor.x + monitor.width):
                x -= (x + w) - (monitor.x + monitor.width)

            if middle:
                x += button_w/2
                y -= button_h/2

            gravity = gtk.gdk.GRAVITY_NORTH_WEST
        elif orient == gnomeapplet.ORIENT_UP:
            y -= h

            if ((x + w) > monitor.x + monitor.width):
                x -= (x + w) - (monitor.x + monitor.width)

            if middle:
                x += button_w/2
                y += h/2

            gravity = gtk.gdk.GRAVITY_SOUTH_WEST

        return (x, y, gravity)

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