"""Mongodb implementations of osid managers."""

# pylint: disable=no-init
#     Numerous classes don't require __init__.
# pylint: disable=too-many-public-methods,too-few-public-methods
#     Number of methods are defined in specification
# pylint: disable=protected-access
#     Access to protected methods allowed in package mongo package scope
# pylint: disable=too-many-ancestors
#     Inheritance defined in specification



from pymongo import MongoClient


from . import profile
from .. import MONGO_CLIENT
from .. import utilities
from ...abstract_osid.osid import managers as abc_osid_managers
from ..primitives import DisplayText
from ..primitives import Id
from ..primitives import Type
from dlkit.abstract_osid.osid import errors
from dlkit.mongo.osid import markers as osid_markers




class OsidProfile(abc_osid_managers.OsidProfile, osid_markers.Sourceable):
    """The ``OsidProfile`` defines the interoperability areas of an OSID.


    An ``OsidProfile`` is implemented by an ``OsidManager``. The top
    level ``OsidProfile`` tests for version compatibility. Each OSID
    extends this interface to include its own interoperability
    definitions within its managers.


    """




    def __init__(self):
        self._runtime = None
        self._config = None


    def _get_registry(self, entry):
        # get from the runtime
        try:
            records_location_param_id = Id('parameter:recordsRegistry@mongo')
            registry = self._runtime.get_configuration().get_value_by_parameter(
                records_location_param_id).get_string_value()
            return import_module(registry).__dict__.get(entry, {})
        except (ImportError, AttributeError, KeyError, errors.NotFound):
            return {}


    def _initialize_manager(self, runtime):
        """Sets the runtime, configuration and mongo client"""
        if self._runtime is not None:
            raise errors.IllegalState('this manager has already been initialized.')
        self._runtime = runtime
        self._config = runtime.get_configuration()
        if not MONGO_CLIENT.is_mongo_client_set():
            try:
                mongo_host_param_id = Id('parameter:mongoHostURI@mongo')
                mongo_host = runtime.get_configuration().get_value_by_parameter(mongo_host_param_id).get_string_value()
            except (AttributeError, KeyError, errors.NotFound):
                MONGO_CLIENT.set_mongo_client(MongoClient())
            else:
                MONGO_CLIENT.set_mongo_client(MongoClient(mongo_host))


    def get_id(self):
        """Gets an identifier for this service implementation.


        The identifier is unique among services but multiple
        instantiations of the same service use the same ``Id``. This
        identifier is the same identifier used in managing OSID
        installations.


        return: (osid.id.Id) - the ``Id``
        *compliance: mandatory -- This method must be implemented.*


        """
        return Id(**profile.ID)

    id_ = property(fget=get_id)

    ident = property(fget=get_id)

    def get_display_name(self):
        """Gets a display name for this service implementation.


        return: (osid.locale.DisplayText) - a display name
        *compliance: mandatory -- This method must be implemented.*


        """
        return DisplayText(
            text = profile.DISPLAYNAME,
            language_type=Type(**profile.LANGUAGETYPE),
            script_type=Type(**profile.SCRIPTTYPE),
            format_type=Type(**profile.FORMATTYPE))

    display_name = property(fget=get_display_name)

    def get_description(self):
        """Gets a description of this service implementation.


        return: (osid.locale.DisplayText) - a description
        *compliance: mandatory -- This method must be implemented.*


        """
        return DisplayText(
            text=profile.DESCRIPTION,
            language_type=Type(**profile.LANGUAGETYPE),
            script_type=Type(**profile.SCRIPTTYPE),
            format_type=Type(**profile.FORMATTYPE))

    description = property(fget=get_description)

    def get_version(self):
        """Gets the version of this service implementation.


        return: (osid.installation.Version) - the service implementation
                version
        *compliance: mandatory -- This method must be implemented.*


        """
        ## THIS ALL NEEDS TO BE FIXED:
        #try:
        #    from ..installation.primitives import Version
        #except:
        #    from .common import Version
        #try:
        #    from ..type.primitives import Type
        #except:
        #    from .common import Type
        #return Version(
        #    components=profile.VERSIONCOMPONENTS,
        #    scheme=Type(**profile.VERSIONSCHEME))
        raise errors.Unimplemented()

    version = property(fget=get_version)

    def get_release_date(self):
        """Gets the date this service implementation was released.


        return: (osid.calendaring.DateTime) - the release date
        *compliance: mandatory -- This method must be implemented.*


        """
        # NEED TO IMPLEMENT
        raise errors.Unimplemented()

    release_date = property(fget=get_release_date)

    @utilities.arguments_not_none
    def supports_osid_version(self, version):
        """Test for support of an OSID specification version.


        arg:    version (osid.installation.Version): the specification
                version to test
        return: (boolean) - ``true`` if this manager supports the given
                OSID version, ``false`` otherwise
        *compliance: mandatory -- This method must be implemented.*
        *implementation notes*: An implementation may support multiple
        versions of an OSID.


        """
        ## THIS ALL NEEDS TO BE FIXED:
        #try:
        #    from ..installation.primitives import Version
        #except:
        #    from .common import Version
        #try:
        #    from ..type.primitives import Type
        #except:
        #    from .common import Type
        #return Version(
        #    components=profile.OSIDVERSION,
        #    scheme=Type(**profile.VERSIONSCHEME))
        raise errors.Unimplemented()

    def get_locales(self):
        """Gets the locales supported in this service.


        return: (osid.locale.LocaleList) - list of locales supported
        *compliance: mandatory -- This method must be implemented.*


        """
        # NEED TO IMPLEMENT
        raise errors.Unimplemented()

    locales = property(fget=get_locales)

    def supports_journal_rollback(self):
        """Test for support of a journaling rollback service.


        return: (boolean) - ``true`` if this manager supports the
                journal rollback, ``false`` otherwise
        *compliance: mandatory -- This method must be implemented.*


        """
        # Perhaps someday I will support journaling
        return False

    def supports_journal_branching(self):
        """Test for support of a journal branching service.


        return: (boolean) - ``true`` if this manager supports the
                journal branching, ``false`` otherwise
        *compliance: mandatory -- This method must be implemented.*


        """
        # Perhaps someday I will support journaling
        return False

    def get_branch_id(self):
        """Gets the ``Branch Id`` representing this service branch.


        return: (osid.id.Id) - the branch ``Id``
        raise:  Unimplemented - ``supports_journal_branching()`` is
                ``false``
        *compliance: mandatory -- This method must be implemented.*


        """
        # Perhaps someday I will support journaling
        raise errors.Unimplemented()

    branch_id = property(fget=get_branch_id)

    def get_branch(self):
        """Gets this service branch.


        return: (osid.journaling.Branch) - the service branch
        raise:  OperationFailed - unable to complete request
        raise:  Unimplemented - ``supports_journal_branching()`` is
                ``false``
        *compliance: mandatory -- This method must be implemented.*


        """
        # Perhaps someday I will support journaling
        raise errors.Unimplemented()

    branch = property(fget=get_branch)

    def get_proxy_record_types(self):
        """Gets the proxy record ``Types`` supported in this service.


        If no proxy manager is available, an empty list is returned.


        return: (osid.type.TypeList) - list of proxy record types
                supported
        *compliance: mandatory -- This method must be implemented.*


        """
        # NEED TO IMPLEMENT
        raise errors.Unimplemented()

    proxy_record_types = property(fget=get_proxy_record_types)

    @utilities.arguments_not_none
    def supports_proxy_record_type(self, proxy_record_type):
        """Test for support of a proxy type.


        arg:    proxy_record_type (osid.type.Type): a proxy record type
        return: (boolean) - ``true`` if this service supports the given
                proxy record type, ``false`` otherwise
        raise:  NullArgument - ``proxy_record_type`` is ``null``
        *compliance: mandatory -- This method must be implemented.*


        """
        # NEED TO IMPLEMENT
        raise errors.Unimplemented()


class OsidManager(abc_osid_managers.OsidManager, OsidProfile):
    """The ``OsidManager`` is the top level interface for all OSID managers.


    An OSID manager is instantiated through the ``OsidRuntimeManager``
    and represents an instance of a service. An OSID manager is
    responsible for implementing a profile for a service and creating
    sessions that, in general, correspond to the profile. An application
    need only create a single ``OsidManager`` per service and
    implementors must ensure the ``OsidManager`` is thread-safe ````.
    The ``OsidSessions`` spawned from an OSID manager are dedicated to
    single processing threads. The ``OsidManager`` defines methods in
    common throughout all OSID managers which implement this interface.


    """


    def __init__(self):
        OsidProfile.__init__(self)
    @utilities.arguments_not_none
    def initialize(self, runtime):
        """Initializes this manager.