# -*- coding: utf-8 -*-
# Elisa - Home multimedia server
# Copyright (C) 2006-2008 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 Elisa with Fluendo's plugins.
#
# The GPL part of Elisa is also available under a commercial licensing
# agreement from Fluendo.
# See "LICENSE.Elisa" in the root directory of this distribution package
# for details on that license.


__maintainer__ = 'Benjamin Kampmann <benjamin@fluendo.com>'

from elisa.core.component import Component
from elisa.core.media_uri import MediaUri, ParseException

from elisa.extern.translation import TranslatableSingular

class MenuEntryBuilder(Component):
    """
    Create L{elisa.base_components.model.Model} for specific MenuEntry XML
    tags.

    @ivar activity:               activity which instantiated self
    @type activity:               L{elisa.base_components.activity.Activity}
    @ivar menu_entry_identifiers: MenuEntry identifiers it can handle; in the
                                  XML it is the attribute 'type' of the
                                  'MenuEntry' tags
    @ivar menu_entry_identifiers: list of string
    @ivar model_configs:          the cache of the models. each model should
                                  be referenced there with a key
    @type model_configs:          L{weakref.WeakKeyDirectory}
    """

    def menu_entry_identifiers__get(self):
        return []

    def build_menu_entry(self, parent, xml_node):
        """
        Fills in L{parent} with models created from the XML description
        L{xml_node}.

        If the created models have an attribute 'xml_tag' containing a
        cElementTree, the activity is trying to find a suitable menu_component
        for its children again at loadmore. Don't forget that in that case the
        models needs to be marked as having children.

        @param parent:   the parent, where the menu_entry is in
        @type parent:    L{elisa.plugins.base.models.menu_node_model.MenuNodeModel}
        @param xml_node: XML MenuEntry tag out of which the menu entry is built
        @type xml_node:  cElementTree

        @rtype:     L{twisted.internet.defer.Deferred}
        @return:    the callback of this Deferred is a list of the created
                    models    
        """
        raise NotImplemented


    # Helper Methods
    def _make_label(self, label_tag):
        """
        make a label out of the label_tag. The return is something that can be
        used in in the menu_node_model-label directly
        """
        if label_tag == None:
            return '<Not specified>'

        domain = label_tag.get('translate-domain', None)
        if domain != None:
            return TranslatableSingular(domain, label_tag.text)

        return label_tag.text

    def _make_config(self, node, default):
        """
        Read the configuration node and return a new L{ModelConfig}, that
        contains the configuration for this subpart. This is a mix of the
        default configuration it got and the new it read. The new ones are
        priorized.
        """

        config = default.copy()

        # remove the special xml_tag if listed
        if config.has_key('xml_tag'):
            config.pop('xml_tag')

        # no node, we have the same config as before
        if node == None:
            return config

        overwriter = ['DefaultFilesIcon',
                      'DefaultDirsIcon',
                      'ContentType',
                      'MediaFilter']

        # Search for differences
        for key in overwriter:
            sub_node = node.find(key)
            if sub_node != None:
                self.debug("Setting %s to %s" % (key, sub_node.text))
                config[key] = sub_node.text

        return config


    def _set_icon(self, model, icon_tag, fallback=None):
        """
        Set the icon on the model according to the icon_tag
        """
        if icon_tag == None:
            if fallback:
                model.theme_icon = fallback
            return

        i_type = icon_tag.get('type', 'theme').lower()
        value = icon_tag.text

        if i_type == 'theme':
            model.theme_icon = value

        elif i_type == 'uri':
            try:
                uri = MediaUri(value)
                model.thumbnail_source = uri
            except ParseException, exc:
                self.warning("'%s' is not a valid uri: %s" % (value, exc))

        elif i_type == 'path':
            try:
                uri = MediaUri("file://%s" % value)
                model.thumbnail_source = uri
            except ParseException, exc:
                self.warning("'%s' is not a valid path: %s" % (value, exc))

        else:
            self.warning("%s has an unsupported type" % icon_tag)


