# test_service_accessor.py
#
# Project: AutoArchive
# License: GNU GPLv3
#
# Copyright (C) 2003 - 2023 Róbert Čerňanský



__all__ = ["TestServiceAccessor"]



import unittest

from AutoArchive._infrastructure.py_additions import staticproperty
from AutoArchive._infrastructure.service import IService
from AutoArchive.tests import ComponentTestUtils
from .. import IServiceIdentification
from .._service_accessor import ServiceAccessor



class TestServiceAccessor(unittest.TestCase):
    "Test of :class:`ServiceAccessor` class."

    @classmethod
    def setUpClass(cls):
        ComponentTestUtils.setUpClassComponent()



    @classmethod
    def tearDownClass(cls):
        ComponentTestUtils.tearDownClassComponent()



    def setUp(self):
        self.__serviceAccessor = ServiceAccessor(ComponentTestUtils.getComponentTestContext().workDir)



    def test_registerService(self):
        """Test service registration.

        Registers a service stub then retrieves it and checks that the returned service is instance of registered
        class."""

        providerIdentification = "test_provider_id"
        self.__serviceAccessor.registerService(_ServiceIdentificationStub, _ServiceStub1, providerIdentification)

        service = self.__serviceAccessor.getOrCreateService(_ServiceIdentificationStub, providerIdentification)

        self.assertIsInstance(service, _ServiceStub1, "Returned service provider instance is not of correct type.")



    def test_unregisterService(self):
        """Test service unregistration.

        Registers a service stub then unregisters it.  Operation should not throw an exception.  Then it registers
        the same service again.  If the unregistration was correct it should not throw an exception either."""

        providerIdentification = "test_provider_id"
        self.__serviceAccessor.registerService(_ServiceIdentificationStub, _ServiceStub1, providerIdentification)

        self.__serviceAccessor.unregisterService(_ServiceIdentificationStub)
        self.__serviceAccessor.registerService(_ServiceIdentificationStub, _ServiceStub1, providerIdentification)



    def test_getOrCreateServiceMultipleProviders(self):
        """Test getting a service when multiple providers are registered.

        Registers two service stubs then retrieves one specific and checks that the returned service is the correct
        one."""

        testProviderIdentifications = ("test_provider_id_1", "test_provider_id_2")
        self.__serviceAccessor.registerService(_ServiceIdentificationStub, _ServiceStub1,
                                               testProviderIdentifications[0])
        self.__serviceAccessor.registerService(_ServiceIdentificationStub, _ServiceStub2,
                                               testProviderIdentifications[1])

        service = self.__serviceAccessor.getOrCreateService(_ServiceIdentificationStub,
                                                            testProviderIdentifications[1])

        self.assertIsInstance(service, _ServiceStub2, "Returned service provider instance is not of correct type.")



    def test_getOrCreateServices(self):
        self.__serviceAccessor.registerService(_ServiceIdentificationStub, _ServiceStub1,
                                               "test_provider_id_1")
        self.__serviceAccessor.registerService(_ServiceIdentificationStub, _ServiceStub2,
                                               "test_provider_id_2")

        serviceProviders = self.__serviceAccessor.getOrCreateServices(_ServiceIdentificationStub)

        self.assertIsInstance(next(serviceProviders), _ServiceStub1,
            "First returned instance of the service provider does not match the first registered one.")
        self.assertIsInstance(next(serviceProviders), _ServiceStub2,
            "Second returned instance of the service provider does not match the second registered one.")



class _ServiceStubBase(IService):

    def __init__(self, wokDir: str = None):
        pass



    def anyServiceMethod(self):
        pass



class _ServiceStub1(_ServiceStubBase):
    pass



class _ServiceStub2(_ServiceStubBase):
    pass



class _ServiceIdentificationStub(IServiceIdentification):

    @staticproperty
    def interface():
        return _ServiceStubBase
