# -*- 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.
#
# Authors: Olivier Tilloy <olivier@fluendo.com>
#          Florian Boucault <florian@fluendo.com>

"""
Various widgets used to display the results of a search.
"""

from elisa.core.utils.i18n import install_translation
from elisa.core import common
from elisa.core.utils import notifying_list

from elisa.plugins.pigment.graph.text import Text
from elisa.plugins.pigment.widgets.widget import Widget
from elisa.plugins.pigment.widgets.list_vertical import ListVertical
from elisa.plugins.pigment.widgets.list_horizontal import ListHorizontal
from elisa.plugins.pigment.widgets.box import VBox

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


_ = install_translation('poblesec')


class SearchResultModel(object):
    """
    Reperesent one search result.
    """

    def __init__(self, searcher, result_type, result):
        """
        Constructor.

        @param searcher:      the searcher entry point
        @type searcher:       C{str}
        @param result_type:   the type of results of this category
        @type result_type:    C{str}
        @param result:       the list of results for this category
        @type result:        C{list} of L{elisa.plugins.base.models}.*
        """
        self.searcher = searcher
        self.result_type = result_type
        self.result = result

class SearchResultWidget(PanelButton):
    """
    A widget used to display the contents of a L{SearchResultModel}.
    """

    def __init__(self):
	super(SearchResultWidget, self).__init__()
	self.panel.set_name("darker")

    def _create_widgets(self):
        super(SearchResultWidget, self)._create_widgets()
        self.label = Text()
        self.add(self.label, forward_signals=False)
        self.label.visible = True

        self.total = Text()
        self.add(self.total, forward_signals=False)
        self.total.visible = True

    def clean(self):
        self.label = None
        self.total = None
        return super(SearchResultWidget, self).clean()

class SearcherModel(object):
    """
    Represents a searcher's results.
    
    DOCME
    """

    def __init__(self, searcher_entry, mediatype):
        """
        Constructor.

        @param searcher_entry: a searcher entry
        @type searcher_entry:  L{elisa.plugins.poblesec.search_controller.SearcherEntry}
        @param mediatype: DOCME
        @type mediatype: str
        """
        self.searcher_entry = searcher_entry
        self.mediatype = mediatype
        self.results = notifying_list.List()

    def set_results(self, result_model):
        self.results[:] = []

        mediatype_to_result_type = {'music': ['artists', 'albums', 'tracks'],
                                    'videos': ['videos'],
                                    'pictures': ['pictures', 'groups']}

        result_types = mediatype_to_result_type[self.mediatype]
        for result_type in result_types:
            # DOCME
            result = getattr(result_model, result_type)
            item = SearchResultModel(self.searcher_entry.searcher, result_type, result)
            self.results.append(item)


class SearcherWidget(Widget):
    """
    A widget used to display the contents of a L{SearcherModel}.

    @cvar item_widget_class: the class of the widget used to display one search
                             result node (category)
    @type item_widget_class: L{elisa.plugins.pigment.widgets.widget.Widget}
    """

    item_widget_class = SearchResultWidget

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

    result_type_to_caption =  {'artists': _("Artist"),
                               'albums': _("Album"),
                               'tracks': _("Track"),
                               'videos': _("Video"),
                               'pictures': _("Picture"),
                               'groups': _("Group"),
                              }

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

    def _create_widgets(self):
        self.title = Text()
        self.add(self.title)
        self.title.visible = True

        # vertical list of results
        self.list = SearcherWidget.ListWidget(widget_class=self.item_widget_class,
                                              visible_range_size=3)
        self.add(self.list)
        self.set_focus_proxy(self.list)
        self.list.set_renderer(self._item_renderer)
        self.list.visible = True

    def clean(self):
        self.title = None
        self.list = None
        return super(SearcherWidget, self).clean()

    def _item_renderer(self, item, widget):
        label = "%s %s" % (self.result_type_to_caption[item.result_type], \
                           _("Results"))
        widget.label.label = label
        total = "<b>%s</b> %s" % (str(len(item.result)), _("Found"))
        widget.total.markup = total



class SearchResultsWidget(VBox):
    """
    A widget that displays the search results for all the searchers of a
    search.
    """
    
    class ListWidget(ListHorizontal):
        widget_signals = {}
        render_empty_items = True

        def _layout_widget(self, widget, position):
            widget.position = (self.compute_x(position), 0.0, 0.0)

    def __init__(self, mediatype, frontend=None):
        """
        Constructor.

        @param mediatype: the type of media searched
        @type mediatype:  C{str}
        """
        super(SearchResultsWidget, self).__init__()
        self.mediatype = mediatype
        self.searchers_results = {}
        # FIXME: passing the frontend around to a widget is a hack; an action
        # could be passed instead executed when a result is clicked
        self._frontend = frontend

    def create_widgets(self):
        self.navigable = True

        self.title = WidgetWithBackground(foreground=Text())
        self.title.visible = True
        self.pack_start(self.title)

        self.list = SearchResultsWidget.ListWidget(SearcherWidget,
                                                   visible_range_size=2)
        self.list.visible = True
        self.list.set_renderer(self._item_renderer)
        self.pack_start(self.list, expand=True)
        self.set_focus_proxy(self.list)        

    def set_searchers(self, searcher_entries):
        """
        Set the list of searchers used for the search and for which results
        should be displayed.

        @param searchers: a list of searcher entries
        @type searchers:  C{list} of
                          L{elisa.plugins.poblesec.search_controller.SearcherEntry}
        """
        for searcher_entry in searcher_entries:
            searcher_model = SearcherModel(searcher_entry, self.mediatype)
            self.searchers_results[searcher_entry] = searcher_model

        self.list.set_model(notifying_list.List(self.searchers_results.values()))

    def set_results(self, searcher_entry, result_model):
        """
        Update the search results for a given searcher entry.

        @param searcher_entry: a searcher entry
        @type searcher_entry:  L{elisa.plugins.poblesec.search_controller.SearcherEntry}
        @param result_model:   the result of a new search
        @type result_model:    one of L{elisa.plugins.search.models}.*
        """
        searcher_model = self.searchers_results[searcher_entry]
        searcher_model.set_results(result_model)

    def _item_renderer(self, item, widget):
        widget.title.label = item.searcher_entry.title
        widget.list.set_model(item.results)

        widget.list.connect('item-activated', self._result_activated_handler)
        # FIXME: disconnect on cleanup

    def _result_activated_handler(self, searcher_widget, result_model):
        browser = self._frontend.retrieve_controllers('/poblesec/browser')[0]
        path = '/poblesec/search/results/%s/%s'
        path = path % (result_model.searcher, result_model.result_type)
        args = {result_model.result_type: result_model.result}
        label = SearcherWidget.result_type_to_caption[result_model.result_type]
        dfr = browser.history.append_controller(path, label, **args)

    @classmethod
    def _demo_widget(cls):
        widget = cls('music')
        widget.title.foreground.label = "EXAMPLE SEARCH RESULTS"
        widget.size = (400.0, 250.0)
        return widget

if __name__ == '__main__':
    from elisa.plugins.poblesec.widgets.search_results import SearchResultsWidget
    SearchResultsWidget.demo()
    try:
        __IPYTHON__
    except NameError:
        import pgm
        pgm.main()
