# -*- 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.
#
# Authors: Benjamin Kampmann <benjamin@fluendo.com>
#          Alessandro Decina <alessandro@fluendo.com>

import sys

from twisted.protocols.amp import Command, String, AmpList, Integer, Float, \
				  Unicode

from elisa.extern.log.log import getFailureMessage
from elisa.core.media_uri import MediaUri
from elisa.plugins.gstreamer.pipeline import GstMetadataPipeline, \
        TimeoutError, GstMetadataError
from elisa.plugins.amp.protocol import MasterFactory, MasterProtocol, \
        SlaveProtocol, SlaveFactory, Union

import gst

class MetadataUnion(Union):
    types = [String(), Integer(), Float(), Unicode()]

class GetMetadata(Command):
    metadata = AmpList([('key', String()), ('value', MetadataUnion(optional=True))])

    arguments = [('uri', String()), ('metadata', metadata)]
    response = [('uri', String()), ('metadata', metadata)]
    errors = {TimeoutError: 'TIMEOUT_ERROR',
            GstMetadataError: 'GST_METADATA_ERROR'}

    del metadata

class AddGstPaths(Command):
    paths = AmpList([('path', String())])
    arguments = [('paths', paths)]
    response = []
    del paths

class GstMetadataMasterProtocol(MasterProtocol):
    ping_period = 11
    ping_timeout = 10

class GstMetadataMasterFactory(MasterFactory):
    protocol = GstMetadataMasterProtocol

class GstMetadataSlaveProtocol(SlaveProtocol):
    ping_period = 11
    ping_timeout = 10

    def __init__(self, cookie):
        SlaveProtocol.__init__(self, cookie)
        self.pipeline = None

    def get_metadata(self, uri, metadata):
        if self.pipeline is None:
            self.pipeline = GstMetadataPipeline()
            self.pipeline.initialize()

        metadata_dict = {'uri': uri}
        for dic in metadata:
            metadata_dict[dic['key']] = None

        dfr = self.pipeline.get_metadata(metadata_dict)
        dfr.addCallback(self._get_metadata_cb)
        dfr.addErrback(self._get_metadata_eb, uri)

        return dfr
    GetMetadata.responder(get_metadata)

    def _get_metadata_cb(self, result):
        lst = []
        for k, v in result.iteritems():
            if v is None:
                continue

            dic = {} 
            if isinstance(v, str):
                typ = String()
            elif isinstance(v, unicode):
                typ = Unicode()
            elif type(v) in (int, long):
                typ = Integer()
            elif type(v) is float:
                typ = Float()
            else:
                continue

            dic['key'] = k
            dic['value'] = (typ, v)
            lst.append(dic)

        return {'uri': str(result['uri']), 'metadata': lst}

    def _get_metadata_eb(self, failure, uri):
        sys.stderr.write('error getting metadata for %s: %s\n' %
                (uri, getFailureMessage(failure)))

        return failure

    def add_gst_paths(self, paths):
        registry = gst.registry_get_default()
        existing = set(registry.get_path_list())
        paths = set([box['path'] for box in paths])
        new = paths - existing
        for path in new:
            registry.add_path(path)
            registry.scan_path(path)

        return {}
    AddGstPaths.responder(add_gst_paths)

class GstMetadataSlaveFactory(SlaveFactory):
    protocol = GstMetadataSlaveProtocol
