# Copyright (C) 2003 Daniel Pearson <daniel.pearson@umbc.edu>
# Copyright (C) 2003 Paramjit Oberoi <param@cs.wisc.edu>
#
# 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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import gtk
import gnome.applet

import socket, errno, os.path

# Register Icons

import icons

# The icons.py module contains string representations of
# icons, created using the "gdk-pixbuf-csource" program.
# The namespace of the module is scanned, and all the
# available icons are registered as stock icons so that
# they can be referenced simply using the icon name.
#
# The gnome convention for icon names is to use dashes
# as in "gtk-clear" or "media-pause".  Python variables
# can't contain dashes, so icons.py contains underscores
# instead, and these are replaced with dashes when the
# icons are registered.

factory = gtk.IconFactory()
factory.add_default()
for k in icons.__dict__.keys():
    if k.startswith("__"): continue
    img = icons.__dict__[k]
    name = "moo-"+k.replace("_","-")
    pixbuf = gtk.gdk.pixbuf_new_from_inline(len(img), img, 0)
    iconset = gtk.IconSet(pixbuf)
    #print "registering icon", name
    factory.add(name, iconset)


class MoosicAppletUI:

    def paused(self):
        self.pause_toggle_icon.set_from_stock('moo-media-pause-red',gtk.ICON_SIZE_BUTTON)
        self.tooltips.set_tip(self.pause_toggle_button, 'Unpause')

    def unpaused(self):
        self.pause_toggle_icon.set_from_stock('moo-media-pause',gtk.ICON_SIZE_BUTTON)
        self.tooltips.set_tip(self.pause_toggle_button, 'Pause')

    def stopped(self):
        self.play_stop_add_icon.set_from_stock('moo-media-play',gtk.ICON_SIZE_BUTTON)
        self.tooltips.set_tip(self.play_stop_add_button, 'Play')

    def playing(self):
        self.play_stop_add_icon.set_from_stock('moo-media-stop',gtk.ICON_SIZE_BUTTON)
        self.tooltips.set_tip(self.play_stop_add_button, 'Stop')

    def empty(self):
        self.play_stop_add_icon.set_from_stock('moo-add',gtk.ICON_SIZE_BUTTON)
        self.tooltips.set_tip(self.play_stop_add_button, 'Add')

    def update_tooltip(self, s):
        #self.tooltips.set_tip(self.app_parent, s)
        #self.tooltips.set_tip(self.applet, s)
        self.tooltips.set_tip(self.ebox, s)

    def queue_running(self):
        self.qstatus_icon.set_from_stock('gtk-yes',gtk.ICON_SIZE_BUTTON)

    def queue_not_running(self):
        self.qstatus_icon.set_from_stock('gtk-no',gtk.ICON_SIZE_BUTTON)

    def loop_mode_enabled(self):
        if self.loop_ebox:
            self.loop_icon.set_from_stock('moo-loop-red',gtk.ICON_SIZE_BUTTON)

    def loop_mode_disabled(self):
        if self.loop_ebox:
            self.loop_icon.set_from_stock('moo-loop-gray',gtk.ICON_SIZE_BUTTON)

    # ---- Buttons

    def create_buttons(self, hbox):
        Buttons = []
        Buttons += [(self.moo.play_stop_add,  'moo-media-play',   'Play')]
        Buttons += [(self.moo.pause_toggle, 'moo-media-pause',  'Pause')]
        Buttons += [(self.moo.prev, 'moo-media-rewind', 'Previous')]
        Buttons += [(self.moo.next, 'moo-media-ffwd',   'Next')]

        for (func,icon, tip) in Buttons:
            button = gtk.Button()
            buttonicon = gtk.image_new_from_stock(icon, gtk.ICON_SIZE_BUTTON)
            button.add(buttonicon)
            # size_request(0) makes the button as small as possible
            # otherwise the button is too large with gtk-2.4
            # (but, this also prevents buttons from expanding
            # automatically if the panel is larger)
            button.set_size_request(-1,0)
            hbox.add(button)
            button.connect("clicked", lambda btn,f=func: f())
            self.__dict__[func.__name__ + "_button"] = button
            self.__dict__[func.__name__ + "_icon"] = buttonicon
            self.tooltips.set_tip(button, tip)

    # ---- Menu entries

    def create_menu(self):
        Menuitems = []
        Menuitems += [(self.moo.add, '_Add Items', 'moo-add')]
        Menuitems += [(self.moo.sort, '_Sort Items', 'gtk-sort-ascending')]
        Menuitems += [(self.moo.shuffle, 'Shu_ffle Items', 'gtk-refresh')]
        Menuitems += [(self.moo.clear, '_Clear Queue', 'gtk-clear')]
        Menuitems += [(self.moo.wipe, 'Clear _Queue and Stop', 'gtk-stop')]
        Menuitems += [(None, None, None)]  # seperator

        # def toggle_loop(self, *args):
        #     print "zz"
        #     self.menu.get_property("Loop")
        # Menuitems += [(toggle_loop, 'toggle_loop', 'gtk-help')]

        Menuitems += [(self.moo.config.prefs_ui, '_Preferences', 'gtk-preferences')]

        # Add entries to the applet's popup menu.
        verbs = []
        xml_template = """<menuitem name="%(name)s" verb="%(name)s" _label="%(label)s"
                                    pixtype="stock" pixname="%(icon-name)s" />"""
        menu_xml = '<popup name="button3">'
        for (func,label,icon) in Menuitems:
            if not func:
                menu_xml += "<separator/>"
            else:
                menu_xml += xml_template % {
                                    "name" : func.__name__,
                                    "label": label,
                                    "icon-name": icon }
                verbs += [(func.__name__, lambda gob,mname,f=func: f())]

        # def loop_verb(gob, name):
        #     print "loop_verb called with",len(args),"arguments"
        #     for i in args: print type(i), i
        #     #import pdb
        #     #pdb.set_trace()
        #
        # self.loop_verb = 0
        # menu_xml += '<menuitem name="Loop" verb="Loop" _label="_Loop" type="toggle" />'
        # verbs += [("Loop", loop_verb)]

        menu_xml += '</popup>'
        self.applet.setup_menu(menu_xml, verbs, None)

    def create_qlength_display(self):
        if not self.qlen_ebox:
            self.qlen_label = gtk.Label()
            self.qlen_label.set_padding(2,0)
            self.qlen_ebox = gtk.EventBox()
            self.qlen_ebox.add(self.qlen_label)
            self.tooltips.set_tip(self.qlen_ebox, "Queue Length")
            self.hbox.add(self.qlen_ebox)
            if self.loop_ebox: self.hbox.reorder_child(self.qlen_ebox,2)
            else: self.hbox.reorder_child(self.qlen_ebox,1)

    def destroy_qlength_display(self):
        if (self.qlen_ebox):
            self.qlen_ebox.destroy()
            self.qlen_ebox = self.qlen_label = None

    def qstatus_icon_clicked(self, ebox, event):
        if event.button == 1:
            self.moo.toggle_queue_running()

    def create_loop_display(self):
        if not self.loop_ebox:
            self.loop_icon = gtk.image_new_from_stock('moo-loop-gray',gtk.ICON_SIZE_BUTTON)
            self.loop_ebox = gtk.EventBox()
            self.loop_ebox.add(self.loop_icon)
            self.loop_ebox.connect("button-press-event",self.loop_icon_clicked)
            self.tooltips.set_tip(self.loop_ebox, "Enable/Disable Loop Mode")
            self.hbox.add(self.loop_ebox)
            self.hbox.reorder_child(self.loop_ebox,1)

    def destroy_loop_display(self):
        if (self.loop_ebox):
            self.loop_ebox.destroy()
            self.loop_ebox = self.loop_label = None

    def loop_icon_clicked(self, ebox, event):
        if event.button == 1:
            self.moo.toggle_loop_mode()

    # ---- Initialize the applet.

    # Widget tree is as follows:
    #
    #     self.applet
    #     |
    #     +--self.frame (for border)
    #        |
    #        +-- self.hbox
    #            |
    #            +--self.qstatus_ebox (to catch clicks on qstatus_icon, and tooltips)
    #            |  |
    #            |  +--self.qstatus_icon
    #            |
    #            +--self.qlen_ebox (queue length tooltip)
    #            |  |
    #            |  +--self.qlen_label
    #            |
    #            +--self.ebox (EventBox for a song-name tooltip)
    #            |  |
    #            |  +--hbox2
    #            |     |
    #            |     +--label
    #            |     |
    #            |     +--bogus-label-for-padding
    #            |
    #            +--Button1
    #            |
    #            +--Button2
    #            |
    #            +--<more buttons...>

    # Each button has a tooltip; self.ebox has a tooltip as well.
    # self.ebox exists only for the tooltip; assigning that tooltip
    # to self.applet leads to the tooltip not being displayed when
    # the mouse is moved off one of the buttons onto other areas.

    def __init__(self, applet, moo):
        self.applet = applet
        self.moo = moo
        self.frame = gtk.Frame()
        # Choose from ETCHED_IN / ETCHED_OUT / IN / OUT / NONE
        self.frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        applet.add(self.frame)

        self.tooltips = gtk.Tooltips()

        self.hbox = gtk.HBox()
        self.frame.add(self.hbox)

        # Queue status
        self.qstatus_ebox = gtk.EventBox()
        self.qstatus_icon = gtk.image_new_from_stock('gtk-no',gtk.ICON_SIZE_BUTTON)
        self.qstatus_ebox.connect("button-press-event",self.qstatus_icon_clicked)
        self.tooltips.set_tip(self.qstatus_ebox, "Start/Stop Queue")
        self.qstatus_ebox.add(self.qstatus_icon)
        self.hbox.add(self.qstatus_ebox)

        # Looping
        self.loop_ebox = self.loop_label = None
        if self.moo.config.display_loop:
            self.create_loop_display()

        # Queue length
        self.qlen_ebox = self.qlen_label = None
        if self.moo.config.display_qlength:
            self.create_qlength_display()

        #self.hbox.add(gtk.image_new_from_stock('moo-loop-red',gtk.ICON_SIZE_BUTTON))
        #self.hbox.add(gtk.image_new_from_stock('moo-loop-gray',gtk.ICON_SIZE_BUTTON))

        self.ebox = gtk.EventBox()
        self.hbox.add(self.ebox)
        hbox2 = gtk.HBox()
        self.ebox.add(hbox2)

        # Current Song
        self.label = gtk.Label("")
        self.label.set_padding(5,0)
        self.label.set_size_request(self.moo.config.width,-1)
        hbox2.add(self.label)

        # dummy label for padding
        # (there must be a better way of doing this)
        # (the alignment widget?)
        l = gtk.Label("")
        l.set_padding(3,0)
        hbox2.add(l)

        #self.app_parent = applet.get_parent()

        self.create_buttons(self.hbox)

        self.create_menu()

        # self.menu = applet.get_popup_component()
        # print self.menu
        # print type(self.menu)
        # print dir(self.menu)

        gtk.timeout_add(500, moo.refresh)

        def bye(*args):
            # this is needed to avoid warnings about leaked objects
            del self.applet
        applet.connect("destroy",bye)

        #pdb.set_trace()

        # How to add a handle to the applet?
        # 4 is supposed to denote the flag PANEL_APPLET_HAS_HANDLE, but it doesn't work
        # (there is also a 'handlebutton' I believe...)
        # self.applet.set_flags(4)

        applet.show_all()

