# -*- 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.
#
# Author: Olivier Tilloy <olivier@fluendo.com>

"""
Functional tests for the Amazon resource provider.
"""

from twisted.trial.unittest import TestCase
from twisted.internet import defer

from elisa.plugins.amazon.resource_provider import AmazonResourceProvider, \
                                                   AWS_SERVER, IMG_SERVER
from elisa.plugins.amazon.models import AmazonItemModel, AmazonItemListModel
from elisa.plugins.amazon.key import AWS_KEY

from elisa.plugins.base.models.media import RawDataModel
from elisa.core.utils.misc import run_functional_tests_check

from elisa.core.media_uri import MediaUri

import binascii

class TestAmazonResourceProvider(TestCase):

    """
    This test case tests the AmazonResourceProvider class.
    """

    def setUp(self):
        run_functional_tests_check()
        def created(provider):
            self.provider = provider
            return provider.initialize()

        create_dfr = AmazonResourceProvider.create({}).addCallback(created)
        return create_dfr

    def tearDown(self):
        return self.provider.clean()

    def check_model_jpeg(self, model):
        """
        Check that the passed model contains raw data for a JPEG image.
        """
        self.failUnless(isinstance(model, RawDataModel))
        header = 'ffd8' + 'ffe0' # SOI marker + JFIF marker
        self.failUnlessEqual(binascii.hexlify(model.data[:4]), header)
        return model

    def test_get_wrong_uri(self):
        """
        Test trying to get a unexisting URI.
        """
        uri = 'http://%s/onca/xml?crap' % AWS_SERVER
        result_model, request_defer = self.provider.get(MediaUri(uri))
        self.failUnlessFailure(request_defer, ValueError)
        return request_defer

    def test_get_item_list(self):
        """
        Test querying the Amazon Web Services to retrieve a list of items.
        """
        query = 'http://' + AWS_SERVER + '/onca/xml?'
        query += 'Service=AWSECommerceService'
        query += '&AWSAccessKeyId=%s' % AWS_KEY
        query += '&Operation=ItemSearch&SearchIndex=Music'
        query += '&ResponseGroup=Images'
        query += '&Artist=beatles&Title=revolver'

        def request_done(model):
            self.failUnless(isinstance(model, AmazonItemListModel))
            self.failUnless(reduce(lambda x, y: x and isinstance(y, AmazonItemModel), result_model.items))
            return model

        result_model, request_defer = self.provider.get(MediaUri(query))
        request_defer.addCallback(request_done)
        return request_defer

    def test_get_image(self):
        """
        Test getting an image from the Amazon image server.
        """
        uri = 'http://' + IMG_SERVER + '/images/I/51EQPYFHS3L._SL75_.jpg'
        result_model, request_defer = self.provider.get(MediaUri(uri))
        request_defer.addCallback(self.check_model_jpeg)
        return request_defer

    def test_image_not_found(self):
        """
        Test getting an image that does not exist from the Amazon image server.
        """
        uri = 'http://' + IMG_SERVER + '/images/crap.jpg'
        result_model, request_defer = self.provider.get(MediaUri(uri))
        self.failUnlessFailure(request_defer, IOError)
        return request_defer

    def test_multiple_images_retrieval_stress(self):
        """
        Stress test for concurrent retrieval of multiple images.
        """
        root = 'http://' + IMG_SERVER + '/images/I/'
        ext = '._SL75_.jpg'
        # Covers for the albums of the Beatles
        covers = ['51SKN7EYK4L', '41BMQS09H4L', '21IVvn7zGAL', '31K9PD6V9EL',
                  '51jgtmkJRiL', '510D51P8YKL', '51zM1qAS2iL', '41H2RGWMNAL',
                  '61-fIEhlMaL', '61V1mxQpBhL']

        request_defers = []
        for cover in covers:
            uri = MediaUri(root + cover + ext)
            result_model, request_defer = self.provider.get(uri)
            request_defers.append(request_defer)

        for request_defer in request_defers:
            request_defer.addCallback(self.check_model_jpeg)

        return defer.DeferredList(request_defers)
