
from twisted.internet import defer, reactor

from elisa.core.media_uri import MediaUri
from elisa.core import common
from elisa.extern.coherence.et import parse_xml

from node_builder_test import NodeBuilderTest, StupidModel
from elisa.core.tests.elisa_test_case import ElisaTestCase

from elisa.core.tests.elisa_test_case import BoilerPlateApp, DEFAULT_CONFIG

from elisa.core.observers.list import ListObservable


class StupidObserver(object):

    stopped = False

    def stop(self):
        self.stopped = True

class StupidModelList(ListObservable):
    activity = None

class StupidMetadataManager(object):
    def get_metadata(self, dici):
        return defer.succeed(dici)

class StupidMediaManager(object):
    
    uri_to_media_type = {}
    direct_children_for_uri = {}

    def get_media_type(self, uri):
        uri = unicode(uri)
        media_type = self.uri_to_media_type.get(uri, {'file_type':'nothing'})
        return defer.succeed(media_type)

    def get_direct_children(self, uri, lst):
        uri = unicode(uri)
        children = self.direct_children_for_uri.get(uri, [])
        for i in children:
            lst.append(i)
        return defer.succeed(lst)

    def get_media_type(self, *args):
        return defer.succeed({'file_type':''})


class UriNodeBuilderTest(NodeBuilderTest, ElisaTestCase):
    component_path = 'xmlmenu:uri_node_builder'
    entry_identifiers = ['uri_node']

    def test_build_entry(self):

        data = """
            <MenuEntry type='uri_node'>
                <URI>elisa://localhost/artists</URI>
            </MenuEntry>
            """
        xml = parse_xml(data)
        root = xml.getroot()

        def done_callback(data, test_model):
            # There should be exaclty ONE item
            self.assertEquals(len(test_model.children), 1)
        
        test_model = StupidModel()
        test_model.children = []
        menu_config =  {
                    'DefaultDirsIcon' : 'dir_icon',
                    'DefaultFilesIcon' : 'file_icon',
                    'MediaFilter' : 'ANY',
                    'ContentType' : 'sections' }
        self.xmlmenu._model_configs[test_model] = menu_config

        dfr = self.component.build_menu_entry(test_model, root)
        dfr.addCallback(done_callback, test_model)

    def test_missing_uri_entry(self):

        data = """
            <MenuEntry type='uri_node'>
            </MenuEntry>
            """
        xml = parse_xml(data)
        root = xml.getroot()

        def done_callback(data, test_model):
            # There should be exaclty ONE item
            self.assertEquals(len(test_model.children), 0)
        
        test_model = StupidModel()
        test_model.children = []
        menu_config =  {
                    'DefaultDirsIcon' : 'dir_icon',
                    'DefaultFilesIcon' : 'file_icon',
                    'MediaFilter' : 'ANY',
                    'ContentType' : 'sections' }
        self.xmlmenu._model_configs[test_model] = menu_config

        dfr = self.component.build_menu_entry(test_model, root)
        dfr.addCallback(done_callback, test_model)

    def test_menu_creation(self):
        uri = MediaUri('elisa://localhost/test')
        uri.label = 'test'
        menu = self.component.create_menu_for_uri(uri, {})
        self.failIf(menu is None)
        self.assertEquals(menu.text, uri.label)
        self.assertEquals(menu.activity, self.component)
        self.failUnless(self.component.model_configs.has_key(menu))

    def test_clean_up(self):
        a = StupidObserver()
        self.component._observers['a'] = a
        self.component.clean()
        self.assertEquals(a.stopped, True)

    def test_loadmore(self):
        m = StupidMediaManager()
        m.direct_children_for_uri = {'file:///a' : [(MediaUri('e:/a'), {}),
                                                    (MediaUri('e:/b'), {'default_image':'c'}),
                                                    (MediaUri('e:/c'), {}),
                                                    (MediaUri('e:/d'), {})]}
        m.media_type_for_uri = {'e:/a' : {'file_type' : 'audio'},
                                'e:/b' : {'file_type' : 'video'},
                                'e:/c' : {'file_type' : 'image'},
                                'e:/d' : {'file_type' : 'directory'}
                                }
        common.application.media_manager = m
        common.application.metadata_manager = StupidMetadataManager()
        model = StupidModel()
        model.uri = MediaUri('file:///a')
        self.component.files_index_start = 0
        model.activity = self.component
        menu_config =  {
                    'DefaultDirsIcon' : 'dir_icon',
                    'DefaultFilesIcon' : 'file_icon',
                    'MediaFilter' : 'ANY',
                    'ContentType' : 'sections' }
        self.xmlmenu._model_configs[model] = menu_config
        model.children = StupidModelList()
        dfr = self.component.loadmore(model)
        dfr = defer.Deferred()
        # this is just a kind of guess-trick
        def do_callback(model):
            self.failIf(len(model.children) == 0)
            self.component.unload(model.children)
            self.assertEquals(len(model.children), 4)
            dfr.callback(True)
        
        reactor.callLater(3, do_callback, model)
        return dfr

# Update that path after moving the plugin
from elisa.plugins.xmlmenu.xmlmenu_components.uri_node_builder import MetadataObserver, UriObserver

class ThumbnailModel(object):
    thumbnail_source = None 

class MetadataObserverTest(ElisaTestCase):

    def test_thumbnail_source(self):
        model = ThumbnailModel
        ob = MetadataObserver(model)
        ob.modified('default_image', 'test')
        self.assertEquals(model.thumbnail_source, 'test')

class UriObserverTest(ElisaTestCase):

    def setUp(self):
        ElisaTestCase.setUp(self)
        common.set_application(BoilerPlateApp(DEFAULT_CONFIG,
                                        load_all_plugins=True))
        common.application.media_manager = StupidMediaManager()
        common.application.metadata_manager = StupidMetadataManager()

        self.observer = None
        self.activity = self
        self.player_model = None
        self.files_index_start = 0

    def create_menu_for_uri(self, uri, config):
        registry = common.application.plugin_registry
        # This might returns a deferred!
        menu_model = registry.create_component('base:menu_node_model')
        menu_model.uri = uri
        menu_model.text = uri
        menu_model.activity = self
        return menu_model

    def test_insert_remove(self):
        m = common.application.media_manager
        m.uri_to_media_type = {
            'file:///testdir' : {'file_type' : 'directory'},
            'file:///music1.mp3' : {'file_type' : 'audio'},
            'file:///music2.mp3' : {'file_type' : 'audio'},
            'file:///music3.mp3' : {'file_type' : 'audio'},
            'file:///music4.mp3' : {'file_type' : 'audio'},
            'file:///music5.mp3' : {'file_type' : 'audio'},
            'file:///video1.mp3' : {'file_type' : 'video'},
            'file:///video2.mp3' : {'file_type' : 'video'},
            'file:///video3.mp3' : {'file_type' : 'video'},
            'file:///video4.mp3' : {'file_type' : 'video'},
            'file:///video5.mp3' : {'file_type' : 'video'},
            'file:///image1.mp3' : {'file_type' : 'image'},
            'file:///image2.mp3' : {'file_type' : 'image'},
            'file:///image3.mp3' : {'file_type' : 'image'},
            'file:///image4.mp3' : {'file_type' : 'image'},
            'file:///image5.mp3' : {'file_type' : 'image'},
            }

        first_element_dfr = defer.Deferred()
        model = StupidModel()
        model.activity = self
        model.children = []
        default_config = {
                    'DefaultDirsIcon' : 'dir_icon',
                    'DefaultFilesIcon' : 'file_icon',
                    'MediaFilter' : 'ANY',
                    'ContentType' : 'sections' }
        self.observer = UriObserver(model, default_config, first_element_dfr)

        for key in m.uri_to_media_type.keys():
            self.observer.inserted([(key, {})], -1)

        dfr = defer.Deferred()
        # this is just a kind of guess-trick
        def do_callback():
            self.failIf(len(model.children) == 0)
            self.observer.removed(model.children, 0)
            self.assertEquals(len(model.children), 0)
            dfr.callback(True)
        
        reactor.callLater(3, do_callback)
        return dfr

    def tearDown(self):
        if self.observer:
            self.observer.stop()

