
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, BoilerPlateApp, DEFAULT_CONFIG

class bus(object):

    callbacks_by_klass = {}

    def register(self, callback, klass):

        if not self.callbacks_by_klass.has_key(klass):
            self.callbacks_by_klass[klass] = []

        self.callbacks_by_klass[klass].append(callback)

    
    def send_message(self, msg, sender):
        klass = type(msg)
        if self.callbacks_by_klass.has_key(klass):
            for cb in self.callbacks_by_klass[klass]:
                cb(msg, sender)

class LocationsBuilderTest(NodeBuilderTest, ElisaTestCase):
    component_path = 'xmlmenu:locations_builder'
    entry_identifiers = ['locations']

    def test_locations_initialize(self):
        self.component.config = {'auto_locations' : 1,
                'locations' : [ 'file:///tmp/music',
                                'file:///tmp/media',
                                'file:///tmp/video',
                                'file:///tmp/fotos',
                                'scheme://host/path',
                                ],
                'file:///tmp/music' : {'only_media' : ['audio'],
                                       'location_type' : 'other',
                                       },
                'file:///tmp/video' : {'only_media' : ['video'],
                                       'label' : 'yehaa'
                                      },
                'file:///tmp/media' : {'only_media' : ['audio', 'video']
                                }
                }
        common.application.bus = bus()
        self.component._locations = []
        self.component.initialize()
        locations = self.component._locations

        location_uris = [u'file:///tmp/music', u'file:///tmp/media',
                         u'file:///tmp/video', u'file:///tmp/fotos',
                         u'scheme://host/path']

        location_by_uri = {}

        for location in locations:
            uri = unicode(location.uri)
            location_by_uri[uri] = location
            if uri in location_uris:
                location_uris.remove(uri)

        # lets see, if we found all, even with the wrong scheme
        self.assertEquals(location_uris, [])

        # lets check the attributes are set correctly
        location = location_by_uri[u'file:///tmp/music']
        self.assertEquals(location.media_types, ['audio'])
        # other gets to local as fallback
        self.assertEquals(location.location_type, 'local')

        location = location_by_uri[u'file:///tmp/media']
        self.assertEquals(location.media_types,['audio','video'])
        #self.assertEquals(location.location_type, 'local')

        location = location_by_uri[u'file:///tmp/video']
        self.assertEquals(location.media_types, ['video'])
        self.assertEquals(location.location_type, 'local')
        self.assertEquals(location.uri.label, 'yehaa')

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

        def done_callback(data,test_model):
            # it has to contain at least our 5 Items!
            self.failIf(len(test_model.children) < 5)
        
        test_model = StupidModel()
        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)
        return dfr

    def test_parent_node_appear(self):
        data = """
            <MenuEntry type='locations'>
                <ParentNode>
                    <Label translate-domain='elisa-base'>Folders</Label>
                    <Icon>audio_by_folder_icon</Icon>
                </ParentNode>
            </MenuEntry>
            """
        root = parse_xml(data).getroot()

        def done_callback(data,test_model):
            # it has to contain at least our 5 Items!
            self.failIf(len(test_model.children) < 5)
        
        test_model = StupidModel()
        test_model.activity = self.xmlmenu
        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)
        return dfr

    def test_parent_node_not_appear(self):
        data = """
            <MenuEntry type='locations'>
                <ParentNode>
                    <Label>test_folder</Label>
                    <Icon>audio_by_folder_icon</Icon>
                </ParentNode>
                <Filter type='uri_scheme'>foo:bar</Filter>
            </MenuEntry>
            """
        root = parse_xml(data).getroot()

        def done_callback(data,test_model):
            # it has to contain at least our 5 Items!
            for item in test_model.children:
                # fail, if the test_folder is in the list
                self.failIf(item.text == 'test_folder')
                    
        
        test_model = StupidModel()
        test_model.activity = self.xmlmenu
        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)
        return dfr

    # FIXME: add XDG/Windows-XDG-test, anybody an Idea, how to test it proper?

    def test_bus_messages(self):

        plugin_registry = common.application.plugin_registry
        MediaLocationMessage = plugin_registry.get_component_class('base:media_location_message')
        InternetLocationMessage = plugin_registry.get_component_class('base:internet_location_message')
        DeviceActionMessage = plugin_registry.get_component_class('base:device_action_message')
        LocalNetworkLocationMessage = plugin_registry.get_component_class('base:local_network_location_message')
        ForeignApplicationMessage = plugin_registry.get_component_class('base:foreign_application_message')
        LocationsListMessage = plugin_registry.get_component_class('xmlmenu:locations_list_message')


        a = MediaLocationMessage.ActionType.LOCATION_ADDED

        # Test, if the messages got set correctly
        self.component._locations = []
        d = DeviceActionMessage(a,'','','file:///')
        self.component._got_bus_message(d, self)
        location = self.component._locations[0]
        self.assertEquals(location.location_type, 'device')

        self.component._locations = []
        d = ForeignApplicationMessage(a,'','','file:///')
        self.component._got_bus_message(d, self)
        location = self.component._locations[0]
        self.assertEquals(location.location_type, 'app')

        self.component._locations = []
        d = InternetLocationMessage(a,'','','file:///')
        self.component._got_bus_message(d, self)
        location = self.component._locations[0]
        self.assertEquals(location.location_type, 'internet')

        self.component._locations = []
        d = LocalNetworkLocationMessage(a,'','','file:///')
        self.component._got_bus_message(d, self)
        location = self.component._locations[0]
        self.assertEquals(location.location_type, 'network')

        # Let's also see, if all attributes get set correctly:


        self.component._locations = []
        d = LocalNetworkLocationMessage(a,'b','c','file:///',
                                        theme_icon='theme',
                                        media_types=['hehe'],)
        self.component._got_bus_message(d, self)
        location = self.component._locations[0]
        self.assertEquals(location.location_type, 'network')
        self.assertEquals(unicode(location.uri), u'file:///')
        self.assertEquals(location.theme_icon, 'theme')
        self.assertEquals(location.media_types, ['hehe'])

        # and remove it again
        d.action = MediaLocationMessage.ActionType.LOCATION_REMOVED
        self.component._got_bus_message(d, self)
        self.assertEquals(self.component._locations, [])



