# -*- coding: utf-8 -*-
# Moovida - Home multimedia server
# Copyright (C) 2006-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.

from elisa.core import media_uri
from elisa.core.utils import locale_helper
from elisa.core.tests.elisa_test_case import ElisaTestCase
import os, platform

class TestMediaURI(ElisaTestCase):

    samples = [u'file:///home/phil/media/La maison de mon r\xeave',
               u'http://google.com',
               u'smb://philn/phil',
               u'smb:///',
               u'smb://phil:foo@philn/phil',
               u'http://192.168.1.0:10243/foo.mp3',
               u'scheme://test',
               u'http://192.168.1.0:10243/û.mp3',
               u'http://192.168.1.0:10243/é.mp3',
               u'http://google.com#test',
               u'file:///truc',

               #u'http://192.168.1.0:10243/\xe9.mp3',
               ]

    def test_samples(self):
        for url in self.samples:
            try:
                uri = media_uri.MediaUri(url)
            except Exception, exc:
                print url
                self.fail("URI Sample %r failed: %s" % (url, exc))
            try:
                unicode(uri)
            except Exception, exc:
                print url
                #import pdb; pdb.set_trace()
                self.fail("unicode(%s) failed: %s" % (url, exc))

            self.assertEquals(unicode(uri), url)

            if not url.endswith(u'/'):
                url2 = u"%s/" % url
                uri = media_uri.MediaUri(url2)
                self.assertEquals(unicode(uri), url2)

    def test_port(self):
        loc = "daap://192.168.1.73:3689"
        uri = media_uri.MediaUri(loc)
        self.assertEquals(uri.port, 3689)

        #Empty port
        loc = "daap://192.168.1.73:/"
        uri = media_uri.MediaUri(loc)
        self.assertEquals(uri.port, -1)

    def test_windows_path(self):
        uri = media_uri.MediaUri(u'file:///c:/home/phil/foo.mp3')
        self.assertEqual(str(uri), 'file:///c:/home/phil/foo.mp3')

        if platform.system() == 'Windows':
            self.assertEqual(uri.path, u'c:/home/phil/foo.mp3')
        else:
            self.assertEqual(uri.path, u'/c:/home/phil/foo.mp3')

        uri_parts = {'scheme': 'file',
                     'path': "c:\\home\\phil\\foo.mp3"
                    }
        uri = media_uri.MediaUri(uri_parts)
        self.assertEqual(str(uri), 'file:///c:/home/phil/foo.mp3')

        uri = media_uri.MediaUri(u'file://c:/home/phil/foo.mp3')
        self.assertEqual(str(uri), 'file:///c:/home/phil/foo.mp3')

        if platform.system() == 'Windows':
            self.assertEqual(uri.path, u'c:/home/phil/foo.mp3')
        else:
            self.assertEqual(uri.path, u'/c:/home/phil/foo.mp3')

        uri_parts = {'scheme': 'file',
                     'path': "c:\\home\\phil\\foo.mp3"
                    }
        uri = media_uri.MediaUri(uri_parts)
        self.assertEqual(str(uri), 'file:///c:/home/phil/foo.mp3')

        uri = media_uri.MediaUri(u'http:///')
        self.assertEqual(str(uri), 'http:///')
        self.assertEqual(uri.path, '/')

        uri = media_uri.MediaUri(u'http://')
        self.assertEqual(str(uri), 'http://')
        self.assertEqual(uri.path, '')

        uri = media_uri.MediaUri(u'file:///')
        self.assertEqual(str(uri), u'file:///')
        if platform.system() == 'Windows':
            self.assertEqual(uri.path, u'')
        else:
            self.assertEqual(uri.path, u'/')

        if platform.system() == 'Windows':
            self.assertEqual(uri.path, u'')
        else:
            self.assertEqual(uri.path, u'/')

        uri = media_uri.MediaUri(u"file:///c:\\home\\phil\\foo.mp3")
        self.assertEqual(str(uri), 'file:///c:/home/phil/foo.mp3')
        self.assertEqual(uri.filename, 'foo.mp3')

    def test_escape(self):
        uri = media_uri.MediaUri(u'file:///home/phil/foo?.mp3')
        if platform.system() == 'Windows':
            self.assertEqual(uri.path, u'home/phil/foo')
        else:
            self.assertEqual(uri.path, u'/home/phil/foo')

        uri = media_uri.MediaUri(u'file:///c:/home/phil/foo?.mp3')
        if platform.system() == 'Windows':
            self.assertEqual(uri.path, u'c:/home/phil/foo')
        else:
            self.assertEqual(uri.path, u'/c:/home/phil/foo')

    def test_smb(self):
        uri = media_uri.MediaUri(u"smb://philn:foo@phil/bare")
        expected_parts = {u'password': u'foo', u'fragment': u'',
                          u'host': u'phil', u'path':u'/bare',
                          u'user': u'philn',
                          u'scheme': u'smb', u'port': 0}
        for k, v in expected_parts.iteritems():
            fail = "%s value unexpected: %r. got %r" % (k,v, getattr(uri, k))
            self.assertEquals(getattr(uri, k), v, fail)

    def test_unicode(self):
        u = u'file:///home/phil/\ufffd'
        uri = media_uri.MediaUri(u)
        self.assertEqual(unicode(uri), u)
        u = u'file:///home/phil/héoui.txt'
        uri = media_uri.MediaUri(u)
        self.assertEqual(unicode(uri), u)

        u = u'file:///path/to/some_where - †'
        uri = media_uri.MediaUri(u)
        self.assertEquals(unicode(uri), u)
        self.assertEquals(unicode(uri.label), u'some_where - †')
        if platform.system() == 'Windows':
            self.assertEquals(uri.path, u'path/to/some_where - †')
        else:
            self.assertEquals(uri.path, u'/path/to/some_where - †')

        self.assertEquals(uri.scheme, u'file')

##         u = u'file:///home/phil/\ufffd'
##         uri = media_uri.MediaUri(u)
##         self.assertEqual(str(uri), misc.fs_encode(u))

    def test_no_unicode(self):
        # FIXME: this fails with LANG=C environment
        u = 'file:///Vidéos'
        uri = media_uri.MediaUri(u)
        # FIXME: this is not a unit test for the media_uri as it stands and
        # fails with the not unit tested local_helper.system_encoding method
        self.assertEqual(unicode(uri), unicode(u, locale_helper.system_encoding()))

    test_no_unicode.todo = "refactor test"

    def test_parameters(self):
        location = u'http://192.168.2.69:10243/WMCv2/%7b9B3A580F-68E8-4701-B8D8-9708E6E5E4F6%7d/103-1.wma?format=PCM'
        uri = media_uri.MediaUri(location)
        self.assertEqual(uri.get_param(u'format'), 'PCM')

        # Windows Media Connect fancy urls
        location = u'http://192.168.1.87:10243/WMPNSSv4/3560585789/ezA1NDZBRDk5LTU3QkEtNENFOS04QjBFLThCQTUxRDFENUU0Qn0uMC5GRDNGRDY3Ng.jpg?width=684,formatID=24,height=456'
        uri = media_uri.MediaUri(location)
        parameters =  {u'formatID':u'24', u'width': u'684',
                                      u'height':u'456'}

        for key in parameters.keys():
            self.assertEqual(uri.get_param(key), parameters[key])

        #self.assertEqual(unicode(uri), location)

        location = u'file:///test/toto?foo=bar bar dflmkds&'
        self.assertRaises(media_uri.ParseException, media_uri.MediaUri,
                          location)


        quoted = media_uri.quote("bar bar foo")
        location = u'file:///test/toto?label=%s' % quoted
        uri = media_uri.MediaUri(location)
        self.assertEqual(uri.get_param('label'), 'bar bar foo')
        self.assertEqual(unicode(uri), location)

        uri2 = media_uri.MediaUri(uri)
        self.assertEqual(uri2.get_param('label'), 'bar bar foo')
        self.assertEqual(unicode(uri2), location)

        params = {'foo': 'hello world', 'bar': '& oui!'}
        quoted_params = '&'.join(["%s=%s" % (k, v)
                                  for (k,v) in media_uri.quote(params).iteritems()])

        location = u'file:///test?%s' % quoted_params
        uri = media_uri.MediaUri(location)
        self.assertEqual(uri.get_param('foo'), params.get('foo'))
        self.assertEqual(uri.get_param('bar'), params.get('bar'))
        self.assertEqual(unicode(uri), location)

        uri = media_uri.MediaUri({'scheme': 'file', 'host': '',
                                  'path': '/test', 'params': params})
        self.assertEqual(uri.get_param('foo'), params.get('foo'))
        self.assertEqual(uri.get_param('bar'), params.get('bar'))
        self.failIfEqual(unicode(uri), location)

        quoted_params = media_uri.quote(params)
        uri = media_uri.MediaUri({'scheme': 'file', 'host': '',
                                  'path': '/test', 'params': quoted_params})
        self.assertEqual(uri.get_param('foo'), params.get('foo'))
        self.assertEqual(uri.get_param('bar'), params.get('bar'))
        self.assertEqual(unicode(uri), location)

        quoted_params = media_uri.quote(params)
        uri = media_uri.MediaUri({'scheme': 'file', 'host': '',
                                  'path': '/test', 'params': quoted_params})
        self.assertEqual(uri.get_param('foo'), params.get('foo'))
        uri.del_param('foo')
        self.assertEqual(uri.get_param('foo', None), None)
        self.assertEqual(uri.get_param('bar'), params.get('bar'))

    def test_quoting(self):
        to_quote = '12345 6789'
        quoted = '12345%206789'
        self.assertEqual(media_uri.quote(to_quote), quoted)

        to_quote = '1 2 3'
        quoted = '1%202%203'
        self.assertEqual(media_uri.quote(to_quote), quoted)

        to_quote = ['1 ', '2 ', '3 ']
        quoted = ['1%20', '2%20', '3%20']
        self.assertEqual(media_uri.quote(to_quote), quoted)

        to_quote = {'1' : 'one', '2' : ' two ', '3': ' three '}
        quoted = {'1' : 'one', '2': '%20two%20', '3' : '%20three%20'}
        self.assertEqual(media_uri.quote(to_quote), quoted)

    def test_not_quote(self):
        to_quote = '12345 6789'
        quoted = '12345 6789'
        self.assertEqual(media_uri.quote(to_quote, not_quote=' '), quoted)

        to_quote = '12345 67/89'
        quoted = '12345%2067/89'
        self.assertEqual(media_uri.quote(to_quote, not_quote='/'), quoted)

    def test_back_slash(self):
        uri = media_uri.MediaUri("file:///test/foo\\x")
        self.assertEqual(str(uri), 'file:///test/foo/x')

        parts = {'scheme': 'file', 'path': "/test/foo\\x"}
        uri = media_uri.MediaUri(parts)
        self.assertEqual(str(uri), 'file:///test/foo/x')


    def test_unquoting(self):
        unquoted = '12345 6789'
        to_unquote = '12345%206789'
        self.assertEqual(media_uri.unquote(to_unquote), unquoted)

        unquoted = '1 2 3'
        to_unquote = '1%202%203'
        self.assertEqual(media_uri.unquote(to_unquote), unquoted)

        unquoted = ['1 ', '2 ', '3 ']
        to_unquote = ['1%20', '2%20', '3%20']
        self.assertEqual(media_uri.unquote(to_unquote), unquoted)

        unquoted = {'1' : 'one', '2' : ' two ', '3': ' three '}
        to_unquote = {'1' : 'one', '2': '%20two%20', '3' : '%20three%20'}
        self.assertEqual(media_uri.unquote(to_unquote), unquoted)

        unquoted = u'bj\xf6rk'
        to_unquote = 'bj%C3%B6rk'
        self.assertEqual(media_uri.unquote(to_unquote), unquoted)

    def test_relative(self):
        location = u'file://./test/toto'
        uri = media_uri.MediaUri(location)
        cwd = os.getcwd()
        if platform.system() == 'Windows':
            cwd = '/' + cwd.replace('\\', '/')

        self.assertEqual(repr(uri), u"MediaUri(u'file://%s/test/toto')" % cwd)

    def test_uri_parts(self):
        # FIXME: this fails with LANG=C
        uri_parts = {}
        uri_parts['scheme'] = 'scheme'
        uri_parts['user'] = 'user'
        uri_parts['password'] = 'password'
        uri_parts['host'] = 'host.com'
        uri_parts['port'] = 80
        uri_parts['path'] = '/test.html'
        uri_parts['fragment'] = 'truc'
        uri_parts['params'] = {}
        uri_parts['params']['param1'] = '1'
        uri_parts['params']['param2'] = '2'
        uri = media_uri.MediaUri(uri_parts)
        loc = u"MediaUri(u'scheme://user:password@host.com:80/test.html?param2=2&param1=1#truc')"
        self.assertEqual(repr(uri), loc)

        uri_parts = {}
        uri_parts['scheme'] = 'scheme'
        uri_parts['user'] = 'user'
        uri_parts['password'] = 'password'
        uri_parts['host'] = 'host.com'
        uri_parts['port'] = 80
        uri_parts['path'] = u'/test- † -html'
        uri_parts['fragment'] = 'truc'
        uri_parts['params'] = {}
        uri_parts['params']['param1'] = '1'
        uri_parts['params']['param2'] = '2'
        uri = media_uri.MediaUri(uri_parts)
        loc = u'scheme://user:password@host.com:80/test- † -html?param2=2&param1=1#truc'
#        self.assertEqual(uri.path,u'/test- † -html')

        self.assertEqual(unicode(uri), loc)

    test_uri_parts.todo = "refactor unittest"

    def test_partial_uri_parts(self):
        uri = media_uri.MediaUri({'scheme':'file', 'path': u'/tmp'})
        loc = u'file:///tmp'
        self.assertEqual(unicode(uri), loc)
        self.assertEqual(str(uri), str(loc))

    def test_label(self):
        loc = u'file:///truc/bidule'
        uri = media_uri.MediaUri(loc)
        uri.label = 'LABEL'
        self.assertEqual(uri.label, 'LABEL')
        loc = u'file:///truc/bidule'
        uri = media_uri.MediaUri(loc)
        self.assertEqual(uri.label, 'bidule')
        loc = u'file:///truc/bidule/'
        uri = media_uri.MediaUri(loc)
        self.assertEqual(uri.label, 'bidule')

        location = 'http://mydomainname/foo_3245345.jpg'
        uri = media_uri.MediaUri(location)
        self.assertEqual(unicode(uri), location)
        uri.label = 'Blabla Group & Ro'
        self.assertEqual(uri.label, 'Blabla Group & Ro')

    def test_parent(self):
        loc = u'file:///truc'
        uri = media_uri.MediaUri(loc)
        loc2 = u'file:///'
        uri2 = media_uri.MediaUri(loc2)
        self.assertEqual(repr(uri.parent), repr(uri2))
        loc = u'file:///truc/bidule'
        uri = media_uri.MediaUri(loc)
        loc2 = u'file:///truc/'
        uri2 = media_uri.MediaUri(loc2)
        self.assertEqual(repr(uri.parent), repr(uri2))
        loc = u'file:///truc/bidule/index.html'
        uri = media_uri.MediaUri(loc)
        loc2 = u'file:///truc/bidule/'
        uri2 = media_uri.MediaUri(loc2)
        self.assertEqual(repr(uri.parent), repr(uri2))
        loc = u'file:///truc/'
        uri = media_uri.MediaUri(loc)
        loc2 = u'file:///'
        uri2 = media_uri.MediaUri(loc2)
        self.assertEqual(repr(uri.parent), repr(uri2))
        loc = u'file:///truc/index.html?label=seemsSo'
        uri = media_uri.MediaUri(loc)
        loc2 = u'file:///truc/'
        uri2 = media_uri.MediaUri(loc2)
        self.assertEqual(repr(uri.parent), repr(uri2))


    def test_filename(self):
        loc = u'file:///truc'
        uri = media_uri.MediaUri(loc)
        self.assertEqual(uri.filename, u'truc')

        loc = u'file:///truc/'
        uri = media_uri.MediaUri(loc)
        self.assertEqual(uri.filename, u'')

        loc = u'file:///truc/foo.mp3'
        uri = media_uri.MediaUri(loc)
        self.assertEqual(uri.filename, u'foo.mp3')

        loc = u'uri://path/to/foo?label=bar'
        uri = media_uri.MediaUri(loc)
        self.assertEqual(uri.filename, u'foo')

        loc = u'uri://thefirst'
        uri = media_uri.MediaUri(loc)
        self.assertEqual(uri.host, u'thefirst')

    def test_join(self):
        loc = u'file:///truc'
        uri = media_uri.MediaUri(loc)
        joined = media_uri.MediaUri(u'file:///truc/foo.avi')
        new_uri = uri.join(u'foo.avi')
        self.assertEqual(new_uri.path, joined.path)
        self.assertEqual(new_uri, joined)

        uri = media_uri.MediaUri(u'file:///tmp/')
        joined = media_uri.MediaUri(u'file:///tmp/foo.avi')
        new_uri = uri.join('foo.avi')
        self.assertEqual(new_uri.path, joined.path)
        self.assertEqual(new_uri, joined)

    def test_extension(self):
        loc = u'file:///truc'
        uri = media_uri.MediaUri(loc)
        self.assertEqual(uri.extension, '')

        loc = u'file:///truc.foo'
        uri = media_uri.MediaUri(loc)
        self.assertEqual(uri.extension, 'foo')

        loc = u'file:///truc.BAR'
        uri = media_uri.MediaUri(loc)
        self.assertEqual(uri.extension, 'bar')

    def test_root_file_scheme(self):
        root_loc1 = 'file:///'
        root_uri1 = media_uri.MediaUri(root_loc1)
        self.assertEqual(str(root_uri1), root_loc1)
        if platform.system() == 'Windows':
            self.assertEqual(root_uri1.path, '')
        else:
            self.assertEqual(root_uri1.path, '/')


        root_loc2 = 'file://'
        root_uri2 = media_uri.MediaUri(root_loc2)
        self.assertEqual(str(root_uri2), 'file:///')
        if platform.system() == 'Windows':
            self.assertEqual(root_uri2.path, '')
        else:
            self.assertEqual(root_uri2.path, '/')

    def test_label(self):
        loc = u'file:///truc.foo/bidule'
        uri = media_uri.MediaUri(loc)

        self.failUnless(isinstance(uri.label, unicode))
        self.assertEqual(uri.label, u"bidule")

        uri.label = "test"
        self.failUnless(isinstance(uri.label, unicode))
        self.assertEqual(uri.label, u"test")

        uri.label = u"truc"
        self.failUnless(isinstance(uri.label, unicode))
        self.assertEqual(uri.label, u"truc")

    def test_uri_from_uri(self):
        loc = u'http://example.net/?ciao=miao'
        uri1 = media_uri.MediaUri(loc)
        uri2 = media_uri.MediaUri(uri1)
        self.assertEqual(repr(uri1), repr(uri2))

        # change a parameter in uri2, should not change uri1
        uri2.set_param('ciao', 'bao')
        self.assertEqual(uri2.get_param('ciao'), 'bao')
        self.assertEqual(uri1.get_param('ciao'), 'miao')

    def test_youtube_uri(self):
        # this uri contains one = in its parameter values
        loc = u'http://www.youtube.com/get_video?video_id=q1UPMEmCqZo&t=vjVQa1PpcFNRpNG84c5Mu6wjLjgW7LFR57-qIGqkzxU=&fmt=18'
        uri = media_uri.MediaUri(loc)
        uri2 = media_uri.MediaUri(uri)
        self.assertEqual(unicode(uri2), unicode(uri))
