import amsoil.core.pluginmanager as pm
from amsoil.core import serviceinterface

import amsoil.core.log
logger=amsoil.core.log.getLogger('gsarpc')

from apiexceptionsv2 import GFedv2NotImplementedError

xmlrpc = pm.getService('xmlrpc')

class GSAv2Handler(xmlrpc.Dispatcher):
    """
    Handle XML-RPC Slice Authority API calls.
    """

    def __init__(self):
        """
        Initialise logger and clear delegate.
        """
        super(GSAv2Handler, self).__init__(logger)
        self._api_tools = pm.getService('apitools')
        self._delegate = None

    # ---- General Methods
    @serviceinterface
    def setDelegate(self, adelegate):
        """
        Set this object's delegate.
        """
        self._delegate = adelegate

    @serviceinterface
    def getDelegate(self):
        """
        Get this object's delegate.
        """
        return self._delegate

    def get_version(self):
        """
        Get details for this Slice Authority implementation.

        Call delegate method and return result or exception.

        """
        try:
            result = self._delegate.get_version()
        except Exception as e:
            return self._api_tools.form_error_return(logger, e)
        return self._api_tools.form_success_return(result)

    def create(self, type_, credentials, options):
        """
        Create object of given type with fields given in options.

        Unwrap 'fields' out of 'options'.

        Call delegate method and return result or exception.

        """
        try:
            fields = self._api_tools.pop_fields(options)
            result = self._delegate.create(type_, self.requestCertificate(), credentials, fields, options)
        except Exception as e:
            return self._api_tools.form_error_return(logger, e)
        return self._api_tools.form_success_return(result)

    def update(self, type_, urn, credentials, options):
        """
        Update object of given type and URN with fields given in options.

        Unwrap 'fields' out of 'options'.

        Call delegate method and return result or exception.

        """
        try:
            fields = self._api_tools.pop_fields(options)
            result = self._delegate.update(type_, urn, self.requestCertificate(), credentials, fields, options)
        except Exception as e:
            return self._api_tools.form_error_return(logger, e)
        return self._api_tools.form_success_return(result)

    def delete(self, type_, urn, credentials, options):
        """
        Delete object of given type and URN.

        Call delegate method and return result or exception.

        """
        try:
            result = self._delegate.delete(type_, urn, self.requestCertificate(), credentials, options)
        except Exception as e:
            return self._api_tools.form_error_return(logger, e)
        return self._api_tools.form_success_return(result)

    def lookup(self, type_, credentials, options):
        """
        Lookup objects with given type.

        Unwrap 'match' and 'filter' fields out of 'options'.

        Call delegate method and return result or exception.
        """
        try:
            match, filter_ = self._api_tools.fetch_match_and_filter(options)
            result = self._delegate.lookup(type_, self.requestCertificate(), credentials, match, filter_, options)

        except Exception as e:
            return self._api_tools.form_error_return(logger, e)
        return self._api_tools.form_success_return(result)

    # ---- Slice Member Service Methods and Project Member Service Methods
    def modify_membership(self, type_, urn, credentials, options):
        """
        Modify information for members that belong to a particular PROJECT or SLICE with given URN.

        Call delegate method and return result or exception.

        """
        try:
            result = self._delegate.modify_membership(type_, urn, self.requestCertificate(), credentials, options)
        except Exception as e:
            return self._api_tools.form_error_return(logger, e)
        return self._api_tools.form_success_return(result)

    def lookup_members(self, type_, urn, credentials, options):
        """
        Lookup information for members that belong to a particular PROJECT or SLICE with given URN.

        Call delegate method and return result or exception.

        """
        try:
            result = self._delegate.lookup_members(type_, urn, self.requestCertificate(), credentials, options)
        except Exception as e:
            return self._api_tools.form_error_return(logger, e)
        return self._api_tools.form_success_return(result)

    def lookup_for_member(self, type_, member_urn, credentials, options):
        """
        Lookup information for a individual member with given URN.

        Call delegate method and return result or exception.
        """
        try:
            result = self._delegate.lookup_for_member(type_, member_urn, self.requestCertificate(), credentials, options)
        except Exception as e:
            return self._api_tools.form_error_return(logger, e)
        return self._api_tools.form_success_return(result)

    def get_credentials(self, slice_urn, credentials, options):
         """
         Provide list of credentials for the caller relative to the given slice.
         """
         try:

              result = self._delegate.get_credentials(slice_urn,  credentials, options)
         except Exception as e:
             return self._api_tools.form_error_return(logger, e)
         return self._api_tools.form_success_return(result)


class GSAv2DelegateBase(object):
    """
    The contract of this class (methods, params and returns) are derived from the GENI Federation MA API (v2).
    """

    def __init__(self):
        super(GSAv2DelegateBase, self).__init__()

    # ---- General methods
    def get_version(self):
        """
        Return information about version and options
          (e.g. filter, query, credential types) accepted by this service

        Arguments: None

        Return:
            get_version structure information as described above
        """
        raise GFedv2NotImplementedError("Method not implemented")

    def create(self, type_, credentials, options):
        """
        Creates a new instance of the given object with a 'fields' option
        specifying particular field values that are to be associated with the object.
        These may only include those fields specified as 'ALLOWED or 'REQUIRED'
        in the 'Creation' column of the object descriptions below
        or in the 'CREATE' key in the supplemental fields in the
        get_version specification for that object.
        If successful, the call returns a dictionary of the fields
        associated with the newly created object.


        Arguments:

           type : type of object to be created
          options:
              'fields', a dictionary field/value pairs for object to be created

        Return:
          Dictionary of object-type specific field/value pairs for created object
        """
        raise GFedv2NotImplementedError("Method not implemented")

    def update(self, type_, urn, credentials, options):
        """
        Updates an object instance specified by URN with a 'fields' option
         specifying the particular fields to update.
        Only a single object can be updated from a single update call.
        The fields may include those specified as 'Yes' in the 'Update' column
        of the object descriptions below, or 'TRUE' in the 'UPDATE' key in the
        supplemental fields provided by the get_version call.
        Note: There may be more than one entity of a given URN at an authority,
        but only one 'live' one (any other is archived and cannot be updated).

        Arguments:
          type: type of object to be updated