# -*- 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.
#
# Author: Olivier Tilloy <olivier@fluendo.com>

"""
An option screen that displays a vertical list of choices.
"""

from elisa.core.input_event import EventValue
from elisa.core.components.model import Model

from elisa.plugins.poblesec.configuration.base import BaseScreen
from elisa.plugins.poblesec.widgets.button import TextButton
from elisa.plugins.poblesec.widgets.sliced_image import SlicedImageHorizontal

from elisa.plugins.pigment.widgets.list_vertical import ListVertical


class ChoiceModel(Model):

    """
    A simple model representing a choice.

    @ivar label:  a label describing the choice
    @type label:  C{unicode}
    @ivar action: the action to trigger
    @type action: C{str}
    """

    def __init__(self):
        super(ChoiceModel, self).__init__()
        self.label = ''
        self.action = ''


class ListScreenWidget(ListVertical):

    """
    A vertical list widget with custom styles.
    """

    pass


class ListScreen(BaseScreen):

    """
    An option screen that displays a vertical list of choices.
    """

    def initialize(self):
        dfr = super(ListScreen, self).initialize()
        dfr.addCallback(self._create_list)
        # setup is populating the list
        dfr.addCallback(lambda result: self.setup())
        return dfr

    def list_renderer(self, item, widget):
        """
        Default renderer for the item widgets in the list.
        Override if needed.

        @param item:   the item to be rendered
        @type item:    L{ChoiceModel}
        @param widget: the widget in which to render the item
        @type widget:  L{elisa.plugins.poblesec.widgets.button.TextButton}
        """
        widget.label = item.label
        # This is a hack to work around a bug in the base pigment list widget
        widget.x = 0.0

    def set_model(self, model):
        """
        Set the model of the list of choices.

        @param model: a list model containing choices
        @type model:  C{list} of L{ChoiceModel}
        """
        self._list.set_model(model)

    def _create_list(self, screen):
        self._list = ListScreenWidget(TextButton)
        self.widget.add(self._list)
        self._list.set_renderer(self.list_renderer)
        self._clicked_id = self._list.connect('item-clicked',
                                              self._option_clicked)
        self._list.visible = True
        self.widget.set_focus_proxy(self._list)

    def set_frontend(self, frontend):
        super(ListScreen, self).set_frontend(frontend)
        self._list.set_selector(self._create_selector())

    def clean(self):
        self._list.disconnect(self._clicked_id)
        self._list.clean()
        self._list = None
        return super(ListScreen, self).clean()

    def _option_clicked(self, widget, option):
        self.choose_option(option)
        if self.standalone:
            self.go_back()

    def choose_option(self, option):
        """
        Select a given option. This is the default behaviour: it saves the
        option and closes the screen. Override if needed.

        @param option: the option selected
        @type option:  L{ChoiceModel}
        """
        self.close(option.action, True)

    def _create_selector(self):
        selector = SlicedImageHorizontal()
        theme = self.frontend.get_theme()
        resource_root = 'elisa.plugins.poblesec.selector'
        left_cap = theme.get_resource('%s_left_cap' % resource_root)
        right_cap = theme.get_resource('%s_right_cap' % resource_root)
        body = theme.get_resource('%s_body' % resource_root)
        selector.left_cap.set_from_file(left_cap)
        selector.right_cap.set_from_file(right_cap)
        selector.body.set_from_file(body)
        selector.visible = True
        return selector

    def handle_input(self, manager, input_event):
        if input_event.value == EventValue.KEY_GO_UP:
            if self._list.selected_item_index > 0:
                self._list.selected_item_index -= 1
                return True
        elif input_event.value == EventValue.KEY_GO_DOWN:
            if self._list.selected_item_index < (len(self._list.model) - 1):
                self._list.selected_item_index += 1
                return True
        elif input_event.value in (EventValue.KEY_OK, EventValue.KEY_RETURN):
            option = self._list.model[self._list.selected_item_index]
            self.choose_option(option)
            if self.standalone:
                self.go_back()
            return True
        return super(ListScreen, self).handle_input(manager, input_event)
