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

import pgm

from pkg_resources import resource_filename

from elisa.core.utils import notifying_list
from elisa.core.input_event import *

from elisa.plugins.pigment import maths
from elisa.plugins.pigment.graph.image import Image
from elisa.plugins.pigment.graph.text import Text
from elisa.plugins.pigment.widgets.widget import Widget
from elisa.plugins.pigment.widgets.const import STATE_DISABLED, STATE_LOADING
from elisa.plugins.pigment.widgets.box import VBox
from elisa.plugins.pigment.widgets.list_horizontal import ListHorizontal
from elisa.plugins.pigment.widgets.list_vertical import ListVertical
from elisa.plugins.pigment.pigment_controller import PigmentController
from elisa.plugins.pigment.animation import implicit

from elisa.plugins.poblesec.widgets.menu_item import MenuItemWidget

import math


NUMBER_OF_MENU_ITEMS = 7
MENU_ITEM_RATIO = 3.824 / (16/9.)


def main_menu_decorate(controller, controller_path, label, icon):
    def create_section_controller(section_controller):
        section_controller.label = label
        section_controller.icon = icon
        controller.model.append(section_controller)
        return section_controller

    dfr = controller.frontend.create_controller(controller_path)
    dfr.addCallback(create_section_controller)
    return dfr


class MainMenuList(ListHorizontal):

    widget_signals = {'clicked': 'item-activated'}

    def _selected_to_range_start(self, selected):
        if not self.is_mapped:
            # if the widget is not yet visible (at start up), we calculate the
            # range so that the selected item is in the middle
            visible_range_start = float(selected)-(self.visible_range_size-1.0)/2.0
        else:
            # 'target_item' is the item pointed by 'selected' index; it has a
            # 'start', that is the position of its beginning, and an 'end',
            # that is the position of its ending
            target_item_start = float(selected)
            target_item_end = float(selected) + 1.0

            # 'partial_item_size' is the amount of space given to items on the
            # sides that are partly visible
            fraction, whole_number = math.modf(self.visible_range_size)
            partial_item_size = fraction/2.0

            # if the target item is not visible or only partially visible
            # compute visible_range_start so that it becomes fully visible and
            # the item after it partly visible
            # otherwise keep visible_range_start as it is
            if self.visible_range_start > target_item_start:
                visible_range_start = target_item_start - partial_item_size
            elif self.visible_range_start + self.visible_range_size < target_item_end:
                visible_range_end = target_item_end + partial_item_size
                visible_range_start = visible_range_end - self.visible_range_size
            else:
                visible_range_start = self.visible_range_start

        min, max = 0.0, len(self.model)-self.visible_range_size
        visible_range_start = maths.clamp(visible_range_start, min, max)

        return visible_range_start

    def compute_opacity(self, index):
        return 255

class MainMenuItemWidget(Widget):

    def __init__(self):
        super(MainMenuItemWidget, self).__init__()
        self._create_widgets()
        self.update_style_properties(self.style.get_items())

    def _create_widgets(self):
        self.container = VBox()
        self.container.visible = True
        self.add(self.container, forward_signals=True)

        self.container.animated.setup_next_animations(duration=200,
                                            transformation=implicit.DECELERATE)

        self.image_section = Widget()
        self.image_section.visible = True
        self.container.pack_start(self.image_section, expand=False)

        self.image_section_bg = Image()
        self.image_section_bg.visible = True
        self.image_section.add(self.image_section_bg)

        self.image = Image()
        self.image.visible = True
        self.image_section.add(self.image)

        self.caption_section = Widget()
        self.caption_section.visible = True
        self.container.pack_start(self.caption_section, expand=False)

        self.caption_section_bg = Image()
        self.caption_section_bg.visible = True
        self.caption_section.add(self.caption_section_bg)

        self.caption = Text()
        self.caption.visible = True
        self.caption_section.add(self.caption)

        self.menu = SectionMenuList(MainMenuButton,
                                    visible_range_size=NUMBER_OF_MENU_ITEMS)
        self.menu.visible = True
        self.container.pack_start(self.menu, expand=True)
        self.container.set_focus_proxy(self.menu)
        self.set_focus_proxy(self.container)

class SectionsMenuController(PigmentController):

    def set_frontend(self, frontend):
        super(SectionsMenuController, self).set_frontend(frontend)

        # menu widget setup
        self.menu = MainMenuList(MainMenuItemWidget)
        self.widget.add(self.menu, forward_signals=False)
        self.widget.set_focus_proxy(self.menu)

        self.model = notifying_list.List()

        self.menu.set_model(self.model)
        self.menu.set_renderer(self._renderer)
        self.menu.set_cleaner(self._cleaner)

    def prepare(self):
        aspect_ratio = self.menu.absolute_width / self.menu.absolute_height
        self.menu.visible_range_size = aspect_ratio * MENU_ITEM_RATIO

    def _renderer(self, controller, widget):
        dfr = self.frontend.load_from_theme(controller.icon, widget.image)
        widget.caption.label = controller.label.upper()
        widget.menu.set_model(controller.model)
        widget.menu.set_renderer(controller.renderer)
        widget.menu.set_cleaner(controller.cleaner)

        widget.menu.connect('item-activated', self._menu_activated_handler,
                            controller)

    def _cleaner(self, widget):
        widget.menu.disconnect_by_func(self._menu_activated_handler)

    def _menu_activated_handler(self, menu, link, section_controller):
        if hasattr(link, 'default_action') and link.default_action is not None:
            return link.default_action.execute(link)

        browser = self.frontend.retrieve_controllers('/poblesec/browser')[0]

        # update browser's title with section's name
        browser.topbar.title.text.label = section_controller.label.upper()

        # create controller corresponding to clicked link
        path = link.controller_path
        label = link.label
        args = link.controller_args

        # The code that toggles the loading state of the activated widget is
        # copy-pasted from the BaseListController.
        widget = menu._widget_from_item_index(menu.model.index(link))
        previous_state = widget.state
        widget.state = STATE_LOADING

        def reset_widget_state(result_or_failure, widget, previous_state):
            widget.state = previous_state

        dfr = browser.history.append_controller(path, label, **args)
        dfr.addBoth(reset_widget_state, widget, previous_state)
        return dfr

    def ready(self):
        # select item in the middle of the list
        if len(self.model) > 0:
            selected = math.ceil(len(self.model)/2.0) - 1
            self.menu.selected_item_index = selected
            self.menu.visible = True


class SectionMenuList(ListVertical):
    widget_signals = {'activated': 'item-activated'}
    render_empty_items = True

class SectionController(PigmentController):

    label = None
    icon = None

    def __init__(self):
        super(SectionController, self).__init__()
        self.model = notifying_list.List()

    def renderer(self, item, widget):
        widget.label.label = item.label

    def cleaner(self, widget):
        widget.label.label = ""


class MainMenuButton(MenuItemWidget):
    def __init__(self):
        super(MainMenuButton, self).__init__(with_artwork_box=False)

