# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""The metaclasses used by the mojo python bindings."""

import itertools
import logging
import sys

# pylint: disable=F0401
import mojo_bindings.messaging as messaging
import mojo_bindings.promise as promise
import mojo_bindings.serialization as serialization
import mojo_system


class MojoEnumType(type):
  """Meta class for enumerations.

  Usage:
    class MyEnum(object):
      __metaclass__ = MojoEnumType
      VALUES = [
        ('A', 0),
        'B',
        ('C', 5),
      ]

      This will define a enum with 3 values, 'A' = 0, 'B' = 1 and 'C' = 5.
  """

  def __new__(mcs, name, bases, dictionary):
    dictionary['__slots__'] = ()
    dictionary['__new__'] = None
    for value in dictionary.pop('VALUES', []):
      if not isinstance(value, tuple):
        raise ValueError('incorrect value: %r' % value)
      key, enum_value = value
      if isinstance(key, str) and isinstance(enum_value, int):
        dictionary[key] = enum_value
      else:
        raise ValueError('incorrect value: %r' % value)
    return type.__new__(mcs, name, bases, dictionary)

  def __setattr__(cls, key, value):
    raise AttributeError('can\'t set attribute')

  def __delattr__(cls, key):
    raise AttributeError('can\'t delete attribute')


class MojoStructType(type):
  """Meta class for structs.

  Usage:
    class MyStruct(object):
      __metaclass__ = MojoStructType
      DESCRIPTOR = {
        'constants': {
          'C1': 1,
          'C2': 2,
        },
        'enums': {
          'ENUM1': [
            ('V1', 1),
            'V2',
          ],
          'ENUM2': [
            ('V1', 1),
            'V2',
          ],
        },
        'fields': [
           SingleFieldGroup('x', _descriptor.TYPE_INT32, 0, 0),
        ],
      }

      This will define an struct, with:
      - 2 constants 'C1' and 'C2';
      - 2 enums 'ENUM1' and 'ENUM2', each of those having 2 values, 'V1' and
        'V2';
      - 1 int32 field named 'x'.
  """

  def __new__(mcs, name, bases, dictionary):
    dictionary['__slots__'] = ('_fields')
    descriptor = dictionary.pop('DESCRIPTOR', {})

    # Add constants
    dictionary.update(descriptor.get('constants', {}))

    # Add enums
    enums = descriptor.get('enums', {})
    for key in enums:
      dictionary[key] = MojoEnumType(key, (object,), { 'VALUES': enums[key] })

    # Add fields
    groups = descriptor.get('fields', [])

    fields = list(
        itertools.chain.from_iterable([group.descriptors for group in groups]))
    fields.sort(key=lambda f: f.index)
    for field in fields:
      dictionary[field.name] = _BuildProperty(field)

    # Add init
    dictionary['__init__'] = _StructInit(fields)

    # Add serialization method
    serialization_object = serialization.Serialization(groups)
    def Serialize(self, handle_offset=0):
      return serialization_object.Serialize(self, handle_offset)
    dictionary['Serialize'] = Serialize

    # pylint: disable=W0212
    def AsDict(self):
      return self._fields
    dictionary['AsDict'] = AsDict

    def Deserialize(cls, context):
      result = cls.__new__(cls)
      fields = {}
      serialization_object.Deserialize(fields, context)
      result._fields = fields
      return result
    dictionary['Deserialize'] = classmethod(Deserialize)

    dictionary['__eq__'] = _StructEq(fields)
    dictionary['__ne__'] = _StructNe

    return type.__new__(mcs, name, bases, dictionary)

  # Prevent adding new attributes, or mutating constants.
  def __setattr__(cls, key, value):
    raise AttributeError('can\'t set attribute')

  # Prevent deleting constants.
  def __delattr__(cls, key):
    raise AttributeError('can\'t delete attribute')


class MojoInterfaceType(type):
  """Meta class for interfaces.

  Usage:
    class MyInterface(object):
      __metaclass__ = MojoInterfaceType
      DESCRIPTOR = {
        'methods': [
          {
            'name': 'FireAndForget',
            'ordinal': 0,
            'parameters': [
              SingleFieldGroup('x', _descriptor.TYPE_INT32, 0, 0),
            ]
          },
          {
            'name': 'Ping',
            'ordinal': 1,
            'parameters': [
              SingleFieldGroup('x', _descriptor.TYPE_INT32, 0, 0),
            ],
            'responses': [
              SingleFieldGroup('x', _descriptor.TYPE_INT32, 0, 0),
            ],
          },
        ],
      }
  """

  def __new__(mcs, name, bases, dictionary):
    # If one of the base class is already an interface type, do not edit the
    # class.
    for base in bases:
      if isinstance(base, mcs):
        return type.__new__(mcs, name, bases, dictionary)

    descriptor = dictionary.pop('DESCRIPTOR', {})

    methods = [_MethodDescriptor(x) for x in descriptor.get('methods', [])]
    for method in methods:
      dictionary[method.name] = _NotImplemented
    fully_qualified_name = descriptor['fully_qualified_name']

    interface_manager = InterfaceManager(fully_qualified_name, methods)
    dictionary.update({
        'manager': None,
        '_interface_manager': interface_manager,
    })

    interface_class = type.__new__(mcs, name, bases, dictionary)
    interface_manager.interface_class = interface_class
    return interface_class

  @property
  def manager(cls):
    return cls._interface_manager

  # Prevent adding new attributes, or mutating constants.
  def __setattr__(cls, key, value):
    raise AttributeError('can\'t set attribute')

  # Prevent deleting constants.
  def __delattr__(cls, key):
    raise AttributeError('can\'t delete attribute')


class InterfaceProxy(object):
  """
  A proxy allows to access a remote interface through a message pipe.
  """
  pass


class InterfaceRequest(object):
  """
  An interface request allows to send a request for an interface to a remote
  object and start using it immediately.
  """

  def __init__(self, handle):
    self._handle = handle

  def IsPending(self):
    return self._handle.IsValid()

  def PassMessagePipe(self):
    result = self._handle
    self._handle = None
    return result

  def Bind(self, impl):
    type(impl).manager.Bind(impl, self.PassMessagePipe())


class InterfaceManager(object):
  """
  Manager for an interface class. The manager contains the operation that allows
  to bind an implementation to a pipe, or to generate a proxy for an interface
  over a pipe.
  """

  def __init__(self, name, methods):
    self.name = name
    self.methods = methods
    self.interface_class = None
    self._proxy_class = None
    self._stub_class = None

  def Proxy(self, handle):
    router = messaging.Router(handle)
    error_handler = _ProxyErrorHandler()
    router.SetErrorHandler(error_handler)
    router.Start()
    return self._InternalProxy(router, error_handler)

  # pylint: disable=W0212
  def Bind(self, impl, handle):
    router = messaging.Router(handle)
    router.SetIncomingMessageReceiver(self._Stub(impl))
    error_handler = _ProxyErrorHandler()
    router.SetErrorHandler(error_handler)

    # Retain the router, until an error happen.
    retainer = _Retainer(router)
    def Cleanup(_):
      retainer.release()
    error_handler.AddCallback(Cleanup)

    # Give an instance manager to the implementation to allow it to close
    # the connection.
    impl.manager = InstanceManager(router, error_handler)

    router.Start()

  def NewRequest(self):
    pipe = mojo_system.MessagePipe()
    return (self.Proxy(pipe.handle0), InterfaceRequest(pipe.handle1))

  def _InternalProxy(self, router, error_handler):
    if error_handler is None:
      error_handler = _ProxyErrorHandler()

    if not self._proxy_class:
      dictionary = {
        '__module__': __name__,
        '__init__': _ProxyInit,
      }
      for method in self.methods:
        dictionary[method.name] = _ProxyMethodCall(method)
      self._proxy_class = type('%sProxy' % self.name,
                               (self.interface_class, InterfaceProxy),
                               dictionary)

    proxy = self._proxy_class(router, error_handler)
    # Give an instance manager to the proxy to allow to close the connection.
    proxy.manager = InstanceManager(router, error_handler)
    return proxy

  def _Stub(self, impl):
    if not self._stub_class:
      accept_method = _StubAccept(self.methods)
      dictionary = {
        '__module__': __name__,
        '__init__': _StubInit,
        'Accept': accept_method,
        'AcceptWithResponder': accept_method,
      }
      self._stub_class = type('%sStub' % self.name,
                              (messaging.MessageReceiverWithResponder,),
                              dictionary)
    return self._stub_class(impl)


class InstanceManager(object):
  """
  Manager for the implementation of an interface or a proxy. The manager allows
  to control the connection over the pipe.
  """
  def __init__(self, router, error_handler):
    self._router = router
    self._error_handler = error_handler
    assert self._error_handler is not None

  def Close(self):
    self._error_handler.OnClose()
    self._router.Close()

  def PassMessagePipe(self):
    self._error_handler.OnClose()
    return self._router.PassMessagePipe()

  def AddOnErrorCallback(self, callback):
    self._error_handler.AddCallback(lambda _: callback(), False)


class _MethodDescriptor(object):
  def __init__(self, descriptor):
    self.name = descriptor['name']
    self.ordinal = descriptor['ordinal']
    self.parameters_struct = _ConstructParameterStruct(
        descriptor['parameters'], self.name, "Parameters")
    self.response_struct = _ConstructParameterStruct(
        descriptor.get('responses'), self.name, "Responses")


def _ConstructParameterStruct(descriptor, name, suffix):
  if descriptor is None:
    return None
  parameter_dictionary = {
    '__metaclass__': MojoStructType,
    '__module__': __name__,
    'DESCRIPTOR': descriptor,
  }
  return MojoStructType(
      '%s%s' % (name, suffix),
      (object,),
      parameter_dictionary)


class _ProxyErrorHandler(messaging.ConnectionErrorHandler):
  def __init__(self):
    messaging.ConnectionErrorHandler.__init__(self)
    self._callbacks = dict()

  def OnError(self, result):
    if self._callbacks is None:
      return
    exception = messaging.MessagingException('Mojo error: %d' % result)
    for (callback, _) in self._callbacks.iteritems():
      callback(exception)
    self._callbacks = None

  def OnClose(self):
    if self._callbacks is None:
      return
    exception = messaging.MessagingException('Router has been closed.')
    for (callback, call_on_close) in self._callbacks.iteritems():
      if call_on_close:
        callback(exception)
    self._callbacks = None

  def AddCallback(self, callback, call_on_close=True):
    if self._callbacks is not None:
      self._callbacks[callback] = call_on_close

  def RemoveCallback(self, callback):
    if self._callbacks:
      del self._callbacks[callback]


class _Retainer(object):

  # Set to force instances to be retained.
  _RETAINED = set()

  def __init__(self, retained):
    self._retained = retained
    _Retainer._RETAINED.add(self)

  def release(self):
    self._retained = None
    _Retainer._RETAINED.remove(self)


def _StructInit(fields):
  def _Init(self, *args, **kwargs):
    if len(args) + len(kwargs) > len(fields):
      raise TypeError('__init__() takes %d argument (%d given)' %
                      (len(fields), len(args) + len(kwargs)))
    self._fields = {}
    for f, a in zip(fields, args):
      self.__setattr__(f.name, a)
    remaining_fields = set(x.name for x in fields[len(args):])
    for name in kwargs:
      if not name in remaining_fields:
        if name in (x.name for x in fields[:len(args)]):
          raise TypeError(
              '__init__() got multiple values for keyword argument %r' % name)
        raise TypeError('__init__() got an unexpected keyword argument %r' %
                        name)
      self.__setattr__(name, kwargs[name])
  return _Init


def _BuildProperty(field):
  """Build the property for the given field."""

  # pylint: disable=W0212
  def Get(self):
    if field.name not in self._fields:
      self._fields[field.name] = field.GetDefaultValue()
    return self._fields[field.name]

  # pylint: disable=W0212
  def Set(self, value):
    self._fields[field.name] = field.field_type.Convert(value)

  return property(Get, Set)


def _StructEq(fields):
  def _Eq(self, other):
    if type(self) is not type(other):
      return False
    for field in fields:
      if getattr(self, field.name) != getattr(other, field.name):
        return False
    return True
  return _Eq

def _StructNe(self, other):
  return not self.__eq__(other)


def _ProxyInit(self, router, error_handler):
  self._router = router
  self._error_handler = error_handler


# pylint: disable=W0212
def _ProxyMethodCall(method):
  flags = messaging.NO_FLAG
  if method.response_struct:
    flags = messaging.MESSAGE_EXPECTS_RESPONSE_FLAG
  def _Call(self, *args, **kwargs):
    def GenerationMethod(resolve, reject):
      message = _GetMessage(method, flags, *args, **kwargs)
      if method.response_struct:
        def Accept(message):
          try:
            assert message.header.message_type == method.ordinal
            payload = message.payload
            response = method.response_struct.Deserialize(
                serialization.RootDeserializationContext(payload.data,
                                                         payload.handles))
            as_dict = response.AsDict()
            if len(as_dict) == 1:
              value = as_dict.values()[0]
              if not isinstance(value, dict):
                response = value
            resolve(response)
            return True
          except Exception as e:
            # Adding traceback similarly to python 3.0 (pep-3134)
            e.__traceback__ = sys.exc_info()[2]
            reject(e)
            return False
          finally:
            self._error_handler.RemoveCallback(reject)

        self._error_handler.AddCallback(reject)
        if not self._router.AcceptWithResponder(
            message, messaging.ForwardingMessageReceiver(Accept)):
          self._error_handler.RemoveCallback(reject)
          reject(messaging.MessagingException("Unable to send message."))
      else:
        if (self._router.Accept(message)):
          resolve(None)
        else:
          reject(messaging.MessagingException("Unable to send message."))
    return promise.Promise(GenerationMethod)
  return _Call


def _GetMessage(method, flags, *args, **kwargs):
  if flags == messaging.MESSAGE_IS_RESPONSE_FLAG:
    struct = method.response_struct(*args, **kwargs)
  else:
    struct = method.parameters_struct(*args, **kwargs)
  header = messaging.MessageHeader(method.ordinal, flags)
  data = header.Serialize()
  (payload, handles) = struct.Serialize()
  data.extend(payload)
  return messaging.Message(data, handles, header)


def _StubInit(self, impl):
  self.impl = impl


def _StubAccept(methods):
  methods_by_ordinal = dict((m.ordinal, m) for m in methods)
  def Accept(self, message, responder=None):
    try:
      header = message.header
      assert header.expects_response == bool(responder)
      assert header.message_type in methods_by_ordinal
      method = methods_by_ordinal[header.message_type]
      payload = message.payload
      parameters = method.parameters_struct.Deserialize(
          serialization.RootDeserializationContext(
              payload.data, payload.handles)).AsDict()
      response = getattr(self.impl, method.name)(**parameters)
      if header.expects_response:
        @promise.async
        def SendResponse(response):
          if isinstance(response, dict):
            response_message = _GetMessage(method,
                                           messaging.MESSAGE_IS_RESPONSE_FLAG,
                                           **response)
          else:
            response_message = _GetMessage(method,
                                           messaging.MESSAGE_IS_RESPONSE_FLAG,
                                           response)
          response_message.header.request_id = header.request_id
          return responder.Accept(response_message)
        p = SendResponse(response)
        if self.impl.manager:
          # Close the connection in case of error.
          p.Catch(lambda _: self.impl.manager.Close())
      return True
    # pylint: disable=W0702
    except:
      # Close the connection in case of error.
      logging.warning(
          'Error occured in accept method. Connection will be closed.')
      logging.debug("Exception", exc_info=True)
      if self.impl.manager:
        self.impl.manager.Close()
      return False
  return Accept


def _NotImplemented(*_1, **_2):
  raise NotImplementedError()
