# -*- coding: utf-8 -*-
# Moovida - Home multimedia server
# Copyright (C) 2006-2009 Fluendo Embedded S.L. (www.fluendo.com).
# All rights reserved.
#
# This file is available under one of two license agreements.
#
# This file is licensed under the GPL version 3.
# See "LICENSE.GPL" in the root of this distribution including a special
# exception to use Moovida with Fluendo's plugins.
#
# The GPL part of Moovida is also available under a commercial licensing
# agreement from Fluendo.
# See "LICENSE.Moovida" in the root directory of this distribution package
# for details on that license.

from elisa.core.utils import locale_helper
from elisa.core.input_event import EventValue
from elisa.core.utils.cancellable_defer import CancelledError

from elisa.plugins.pigment.widgets import const
from elisa.plugins.pigment.widgets.widget import Widget
from elisa.plugins.pigment.widgets.list_vertical import ListVertical
from elisa.plugins.pigment.widgets.box import HBox, ALIGNMENT

from elisa.plugins.poblesec.base.list import BaseListController
from elisa.plugins.poblesec.widgets.menu_item import MenuItemWidget, \
                                                     DoubleLineMenuItemWidget
from elisa.plugins.poblesec.widgets.button import PanelButton
from elisa.plugins.poblesec.widgets.widget_with_actions import WidgetWithActions


class Shortcut(PanelButton):
    pass


class ListItemWidgetWithActions(WidgetWithActions):
    """
    DOCME
    """
    def _create_widgets(self, *args):
        super(ListItemWidgetWithActions, self)._create_widgets(*args)

        self.container = HBox()
        self.container.navigable = True
        self.add(self.container, forward_signals=False)
        self.set_focus_proxy(self.container)

        #FIXME use CSS style
        self.container.alignment = ALIGNMENT.START
        self.container.visible = True

        self.container.pack_start(self.item_widget)
        self.item_widget.visible = True

        self.update_style_properties(self.style.get_items())

    def show_actions(self, actions_widget):
        self.container.pack_start(actions_widget)

    def hide_actions(self, actions_widget):
        self.container.remove(actions_widget)


class SimpleListController(BaseListController):

    list_widget = ListVertical
    item_widget_cls = None
    item_widget_kwargs = {}

    def __init__(self):
        super(SimpleListController, self).__init__()
        self._delayed_actions = None

    def nodes_setup(self):
        item_widget_name = self._view_mode.name
        widget_kwargs = {'contextual_actions': self._contextual_actions,
                         'item_widget_cls': self.item_widget_cls,
                         'item_widget_name': item_widget_name,
                         'item_widget_kwargs': self.item_widget_kwargs}
        self.nodes = self.list_widget(self.node_widget, visible_range_size=10,
                                      widget_kwargs=widget_kwargs)
        self.nodes.start_offset = 1
        self.nodes.set_name("vertical")
        self.nodes.visible = True

        self.widget.set_focus_proxy(self.nodes)

    def fastscroller_setup(self):
        self.fastscroller = ListVertical(Shortcut, visible_range_size=10)
        self.fastscroller.start_offset = 1
        self.fastscroller.render_empty_items = True
        self.fastscroller.set_name("fastscroller") # FIXME: remove name
        self.fastscroller.visible = True

    def layout_components(self):
        self.components_container = HBox()
        self.components_container.set_name('previewlist_components_container')
        self.components_container.navigable = True
        self.components_container.visible = True
        self.widget.add(self.components_container)

        if self.fastscroller is not None:
            self.components_container.pack_start(self.fastscroller)
        self.components_container.pack_end(self.nodes)

        # swallow events to create a 'dead end'
        self.components_container.add_navigation_rule(self.fastscroller, 
                                                      EventValue.KEY_GO_UP, 
                                                      None)
        self.components_container.add_navigation_rule(self.fastscroller, 
                                                      EventValue.KEY_GO_DOWN, 
                                                      None)
        self.components_container.add_navigation_rule(self.nodes, 
                                                      EventValue.KEY_GO_UP, 
                                                      None)
        self.components_container.add_navigation_rule(self.nodes, 
                                                      EventValue.KEY_GO_DOWN, 
                                                      None)

    def shortcut_renderer(self, shortcut, widget):
        # Default implementation
        widget.text.label = shortcut


class PreviewListController(SimpleListController):
    pass


class MenuItemListMixin(object):

    node_widget = ListItemWidgetWithActions
    item_widget_cls = MenuItemWidget

    def node_renderer(self, item, widget):
        """
        Render a node using the common API methods defined by the
        L{elisa.plugins.poblesec.base.list.GenericListViewMode} class.
        """
        # Cancel previous deferred calls for this widget
        self.cancel_deferreds(widget)

        def _failure(failure):
            # Swallow errbacks only when the deferred has been cancelled
            failure.trap(CancelledError)

        # Pass the item to the widget so that contextual actions can use it. 
        widget.item = item

        # Render the label of the widget
        widget.item_widget.label.visible = False
        def got_label(text):
            widget.item_widget.label.label = text
            widget.item_widget.label.visible = True
        label_deferred = self._view_mode.get_label(item)
        label_deferred.addCallbacks(got_label, _failure)
        self.register_deferred(widget, label_deferred)

        # Set the default image of the widget
        artwork_box = widget.item_widget.artwork_box
        artwork_box.icon.clear()
        artwork_box.thumbnail.clear()
        default_image = self._view_mode.get_default_image(item)
        if default_image:
            self.frontend.load_from_theme(default_image, artwork_box.icon)

        # Set the real image of the widget
        theme = self.frontend.get_theme()
        image_deferred = self._view_mode.get_image(item, theme)
        if image_deferred is not None:
            def got_thumbnail(thumbnail_file):
                if thumbnail_file is not None:
                    if not isinstance(thumbnail_file, unicode):
                        thumbnail_file = thumbnail_file.decode(locale_helper.system_encoding())
                    artwork_box.icon.clear()
                    artwork_box.thumbnail.set_from_file(thumbnail_file, 128)

            self.register_deferred(widget, image_deferred)
            image_deferred.addCallbacks(got_thumbnail, _failure)

        # Set info glyphs of the widget
        if hasattr(item, 'static_glyphs'):
            widget.item_widget.static_glyphs = item.static_glyphs
        if hasattr(item, 'dynamic_glyphs'):
            widget.item_widget.dynamic_glyphs = item.dynamic_glyphs


class MenuItemListController(MenuItemListMixin, SimpleListController):
    pass

class MenuItemPreviewListController(MenuItemListMixin, PreviewListController):
    pass


class DoubleLineMenuItemPreviewListController(MenuItemPreviewListController):

    """
    Preview list controller tied to the double line menu item widget.
    """

    item_widget_cls = DoubleLineMenuItemWidget

    def node_renderer(self, item, widget):
        super(DoubleLineMenuItemPreviewListController, self).node_renderer(item, widget)

        def _failure(failure):
            # Swallow errbacks only when the deferred has been cancelled
            failure.trap(CancelledError)

        # Render the sublabel of the widget
        widget.item_widget.sublabel.visible = False
        def got_sublabel(text):
            widget.item_widget.sublabel.label = text
            widget.item_widget.sublabel.visible = True
        sublabel_deferred = self._view_mode.get_sublabel(item)
        sublabel_deferred.addCallbacks(got_sublabel, _failure)
        self.register_deferred(widget, sublabel_deferred)
