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

from elisa.plugins.pigment.graph.image import Image
from elisa.plugins.pigment.widgets import const
from elisa.plugins.pigment.widgets.widget import Widget
from elisa.plugins.pigment.widgets.box import HBox, ALIGNMENT
from elisa.plugins.pigment.widgets.size_enforcer import Square
from elisa.plugins.pigment.animation import implicit

from elisa.plugins.poblesec.widgets.button import PanelButton

from twisted.internet import reactor

import gobject
import pgm


class WidgetWithActions(Widget):
    """
    DOCME
    """

    __gsignals__ = {
        'activated': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
    }

    show_actions_delay = 0.5 # expressed in seconds

    def __init__(self, item_widget_cls, item_widget_name=None, \
                 item_widget_kwargs={}, contextual_actions=[]):
        super(WidgetWithActions, self).__init__()
        self._delayed_show_actions = None
        self._actions_widget = None
        self._contextual_actions = contextual_actions
        self._create_widgets(item_widget_cls, item_widget_name,
                             item_widget_kwargs)
        self.update_style_properties(self.style.get_items())

    def _create_widgets(self, item_widget_cls, item_widget_name, \
                        item_widget_kwargs):
        self.item_widget = item_widget_cls(**item_widget_kwargs)
        self.item_widget.set_name(item_widget_name)
        self.item_widget.connect('activated', self._on_item_activated)

    def _on_item_activated(self, item_widget):
        self.emit('activated')

    def do_state_changed(self, previous_state):
        super(WidgetWithActions, self).do_state_changed(previous_state)
        self.item_widget.state = self.state

        if self.state == const.STATE_SELECTED:
            if self._actions_widget:
                self._actions_widget.animated.update_animation_settings(end_callback=None)
                self._display_actions_animation(self._actions_widget)
            elif not self._delayed_show_actions or not self._delayed_show_actions.active():
                self._delayed_show_actions = \
                    reactor.callLater(self.show_actions_delay, self._create_and_show_actions)
        elif self.state == const.STATE_NORMAL:
            if self._delayed_show_actions and self._delayed_show_actions.active():
                self._delayed_show_actions.cancel()
            else:
                self._hide_and_destroy_actions()

    def _create_and_show_actions(self):
        contextual_actions = self._contextual_actions

        if hasattr(self, 'item') and hasattr(self.item, 'extra_actions') \
                and self.item.extra_actions is not None:
            contextual_actions = self.item.extra_actions

        if contextual_actions:
            self._actions_widget = self._create_actions(contextual_actions)
            self._display_actions_animation(self._actions_widget)
            self.show_actions(self._actions_widget)

    def _create_actions(self, actions):
        actions_widget = HBox()
        actions_widget.navigable = True
        actions_widget.visible = True
        # FIXME use CSS style
        actions_widget.alignment = ALIGNMENT.START 

        for action in actions:
            square = Square()
            square.visible = True

            button = PanelButton()
            button.visible = True
            if action.name is not None:
                button.set_name(action.name)
            action.connect('name-changed', self._action_name_changed, button)
            button.text.alignment = pgm.TEXT_ALIGN_CENTER
            button.connect('activated', self._contextual_action_activated, \
                           action)
            square.button = button
            square.add(button)

            actions_widget.pack_start(square)

        return actions_widget

    def _contextual_action_activated(self, button, action):
        action.execute(self.item)

    def _hide_and_destroy_actions(self):
        if self._actions_widget:
            self._hide_actions_animation(self._actions_widget)

    def _destroy_actions(self, result=None):
        if self._actions_widget:
            for action in self._contextual_actions:
                action.disconnect_by_func(self._action_name_changed)
            self.hide_actions(self._actions_widget)
            for square in self._actions_widget:
                square.button.disconnect_by_func(self._contextual_action_activated)
            self._actions_widget.clean()
            self._actions_widget = None

    def _display_actions_animation(self, actions_widget):
        actions_widget.opacity = 0
        settings = {'duration': 400,
                    'transformation': implicit.SMOOTH}
        actions_widget.animated.setup_next_animations(**settings)
        actions_widget.animated.opacity = 255

    def _hide_actions_animation(self, actions_widget):
        actions_widget.opacity = 255
        settings = {'duration': 400,
                    'transformation': implicit.SMOOTH,
                    'end_callback': self._destroy_actions}

        actions_widget.animated.setup_next_animations(**settings)
        actions_widget.animated.opacity = 0

    def show_actions(self, actions_widget):
        raise NotImplementedError()

    def hide_actions(self, actions_widget):
        raise NotImplementedError()

    def _action_name_changed(self, action, button):
        # The name of an action changed, re-render the corresponding widget
        button.set_name(action.name)

    def clean(self):
        if self._actions_widget != None:
            if self._actions_widget.animated != None:
                self._actions_widget.animated.update_animation_settings(end_callback=None)
                self._actions_widget.animated.stop_animations()

            self._destroy_actions()

        if self._delayed_show_actions and self._delayed_show_actions.active():
            self._delayed_show_actions.cancel()

        return super(WidgetWithActions, self).clean()
