# -*- coding: utf-8 -*-
# Moovida - Home multimedia server
# Copyright (C) 2007-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: Benjamin Kampann <benjamin@fluendo.com>

"""
The Searcher API
"""

from elisa.core.component import Component
from elisa.core.utils import defer

from elisa.core import common
from elisa.core.resource_manager import  ResourceProviderNotFound

class Searcher(Component):
    """
    A searcher is a glue object. It knows how to do a search request for a
    certain API and how to wrap the result into the SearchResultModel.

    A searcher is a sub component of the
    L{elisa.plugins.search.search_metaresource_provider.SearchMetaresourceProvider}.
    It is loaded from the specified entry point and the hold by the provider.

    *Note:* A Searcher should never be called directly but always through the
    search metaresource provider (aside from testcases).

    @cvar paths: the different paths this searcher knows how to handle. For
                 example: 'music', 'pictures'
    @type paths: C{list} of C{str}

    @cvar provider_path: the path to the provider this searcher is for
    @type provider_path: C{str}
    """
    paths = []

    provider_path = None

    def __init__(self):
        super(Searcher, self).__init__()
        self.provider = None
        self.active = True

    def search(self, uri, result_model):
        """
        Trigger a search for C{uri} and fill the C{result_model} with the
        results.

        @param uri:     the original URI that was requested. See the
                        corresponding documentation in L{SearchMetaresource.get}
                        for more informations about it.
        @type uri:      L{elisa.core.media_uri.MediaUri}

        @param result_model: containing the result for this search and should be
                             filled asynchronously in background
        @type result_model:  one of L{elisa.plugins.search.result_models}

        @return:    fired whenever the search is done
        @rtype:     L{elisa.core.utils.cancellable_defer.CancellableDeferred}
        """
        return defer.fail(NotImplementedError())

    def _query_provider(self):
        """
        Internal helper method: query for the resource provider definded by the
        'provider_path'. Return the provider or None if it is not found. For
        performance reasons store the result per session.

        This is a helper method for searcher implementations. A common pattern
        is to request for the resource provider and store a reference to it.
        This can efficiently done like this in the L{search} implementation
        now::
            provider = self._query_provider()
            if provider is None:
                msg = "resource provider %s not found" % name
                return defer.fail(ResourceProviderNotFound(msg))
            ....

        """
        if not self.active:
            return None
        
        if self.provider is None:
            # no provider set yet, try to get one
            try:
                manager = common.application.resource_manager
                # the name of this method is way to long!
                self.provider = manager.get_resource_provider_by_path(self.provider_path)
            except ResourceProviderNotFound:
                # our provider is missing. deactive any further checks
                self.active = False

        return self.provider
