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

"""
This metadata provider, looks if there is might a Cover (file) in the
directory of the file.
"""


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

import os, glob

from twisted.internet import threads

from elisa.core import common
from elisa.base_components.metadata_provider import MetadataProvider
from elisa.core.media_uri import MediaUri


class CoverInDir(MetadataProvider):
    """
    This CoverInDir Metadata Provider just looks if there are might covers in
    the directory of the URI. If there are more than one found, it uses the
    best suited one.

    @ivar list_of_extentions:   a list of extentions our cover could have.
    @type list_of_extentions:   list

    @ivar list_of_names:        a list of names for our cover sorted by
                                priority. if there is none found, which is
                                exactly spelled this way, we'll look for one,
                                which contains any of this names...

    @type list_of_names:        list
    """

    # lowercase only
    list_of_extentions = ['png', 'jpg', 'xpm', 'jpeg']

    # lowercase only
    list_of_names = ['cover', 'front', 'cd', 'dvd']
    # TODO: add some more
    # TODO: Should we use multilingual ones, too?


    def get_rank(self):
        ## We'll look here first
        return 120

    def able_to_handle(self, metadata):
        able = False
        content_type = metadata.get('content-type')
        file_type = metadata.get('file_type')
        
        if metadata.has_key('uri'):
            uri = metadata['uri']
            cover = metadata.get('cover')
            default_image = metadata.get('default_image')
            self.debug("file_type=%r, content_type=%r, uri.scheme=%r",
                       file_type, content_type, uri.scheme)
            if not cover and not default_image:
                able = ((file_type == 'audio') or (content_type in ('artist',
                                                                    'album',
                                                                    'audio'))) \
                       and uri.scheme in ('file', 'elisa')
                
        return able

    def get_metadata(self, metadata, low_priority=False):
        d = threads.deferToThread(self._search_for_cover, metadata)
        return d

    def _find_sub_string(self, data, match_list):
        found = False
        #-1 not in [  for item in match_list ]
        for item in match_list:
            if data.find(item) != -1:
                found = True
                break
        return found

    def _search_for_cover(self, metadata):
        uri = metadata['uri']
        if uri.scheme == 'file':
            result = self._files_scan(metadata)
        else:
            result = self._elisa_db_scan(metadata)
        return result
    
    def _files_scan(self, metadata):
        uri = metadata['uri']
        self.debug("Scanning local files of %r", uri)
        extensions = self.list_of_extentions + \
                     [ e.upper() for e in self.list_of_extentions ]
        parent = uri.parent
        directory = parent.path

        if os.path.isdir(directory):
            file_list = []
            for onefile in os.listdir(directory):
                child = parent.join(onefile)

                # inspect only directory we're looking metadata for
                if os.path.isdir(child.path) and child == uri:
                    for extension in extensions:
                        files = glob.glob('%s/*.%s' % (child.path,
                                                       extension))
                        for filename in files:
                            name, ext = os.path.splitext(filename)
                            name = os.path.basename(name)
                            if self._find_sub_string(name.lower(),
                                                     self.list_of_names):
                                child_uri = MediaUri('file://%s' % filename)
                                file_list.append(child_uri)

                else:
                    name, ext = os.path.splitext(onefile)
                    if ext == '':
                        continue

                    if ext[1:].lower() in self.list_of_extentions and \
                           self._find_sub_string(name.lower(),
                                                 self.list_of_names):
                        file_list.append(child)

            # No suited files found. Return
            if len(file_list) == 0:
                return metadata

            # Only one is found: use it!
            if len(file_list) > 0:
                return self._set_cover(metadata,file_list[0])

    def _elisa_db_scan(self, metadata):
        uri = metadata['uri']
        self.debug("Retrieving cover of %r from db", uri)
        
        def got_children(children):
            if len(children) > 0:
                child_metadata = children[0][1]
                default_image = child_metadata.get('default_image')
                if default_image:
                    return self._set_cover(metadata, default_image)

        media_manager = common.application.media_manager
        dfr = media_manager.get_direct_children(uri, [])
        dfr.addCallback(got_children)
        return metadata

    def _set_cover(self, metadata, cover_path):
        if metadata.get('cover') == None:
            metadata['cover'] = cover_path

        # Set globally image if not set yet:
        if metadata.get('default_image') == None:
            self.debug("Setting default_image to %r", cover_path)
            metadata['default_image'] = cover_path

        return metadata



if __name__ == "__main__":

    from twisted.internet import reactor

    c = CoverInDir()
    uri = MediaUri("file:///tmp/covers/momo.mp3")

    print "rank:",c.get_rank()
    print "Should be able to handle:", c.able_to_handle({'uri':uri})
    print "Should not be able to handle:", c.able_to_handle({'uri' : uri,
                                                        'cover': 'blalbal'})

    def start():

        def print_it(metadata):
            print "metadata is", metadata


        df = c.get_metadata({'uri' : uri})
        df.addCallback(print_it)


    reactor.callWhenRunning(start)

    reactor.run()
