# 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 descriptors used to define generated elements of the mojo python bindings.
"""

import array
import itertools
import struct

import mojo_bindings.reflection as reflection
import mojo_bindings.serialization as serialization

# pylint: disable=E0611,F0401
import mojo_system


class Type(object):
  """Describes the type of a struct field or a method parameter,"""

  def Convert(self, value): # pylint: disable=R0201
    """
    Convert the given value into its canonical representation, raising an
    exception if the value cannot be converted.
    """
    return value

  def GetDefaultValue(self, value):
    """
    Returns the default value for this type associated with the given value.
    This method must be able to correcly handle value being None.
    """
    return self.Convert(value)


class SerializableType(Type):
  """Describe a type that can be serialized by itself."""

  def __init__(self, typecode):
    Type.__init__(self)
    self.typecode = typecode
    self.byte_size = struct.calcsize('<%s' % self.GetTypeCode())

  def GetTypeCode(self):
    """
    Returns the type code (as defined by the struct module) used to encode
    this type.
    """
    return self.typecode

  def GetByteSize(self):
    """
    Returns the size of the encoding of this type.
    """
    return self.byte_size

  def Serialize(self, value, data_offset, data, handle_offset):
    """
    Serialize a value of this type.

    Args:
      value: the value to serialize.
      data_offset: the offset to the end of the data bytearray. Used to encode
                   pointers.
      data: the bytearray to append additional data to.
      handle_offset: the offset to use to encode handles.

    Returns a a tuple where the first element is the value to encode, and the
    second is the array of handles to add to the message.
    """
    raise NotImplementedError()

  def Deserialize(self, value, context):
    """
    Deserialize a value of this type.

    Args:
      value: the base value for this type. This is always a numeric type, and
             corresponds to the first element in the tuple returned by
             Serialize.
      data: the bytearray to retrieve additional data from.
      handles: the array of handles contained in the message to deserialize.

    Returns the deserialized value.
    """
    raise NotImplementedError()


class BooleanType(Type):
  """Type object for booleans"""

  def Convert(self, value):
    return bool(value)


class NumericType(SerializableType):
  """Base Type object for all numeric types"""

  def GetDefaultValue(self, value):
    if value is None:
      return self.Convert(0)
    return self.Convert(value)

  def Serialize(self, value, data_offset, data, handle_offset):
    return (value, [])

  def Deserialize(self, value, context):
    return value


class IntegerType(NumericType):
  """Type object for integer types."""

  def __init__(self, typecode):
    NumericType.__init__(self, typecode)
    size = 8 * self.byte_size
    signed = typecode.islower()
    if signed:
      self._min_value = -(1 << (size - 1))
      self._max_value = (1 << (size - 1)) - 1
    else:
      self._min_value = 0
      self._max_value = (1 << size) - 1

  def Convert(self, value):
    if value is None:
      raise TypeError('None is not an integer.')
    if not isinstance(value, (int, long)):
      raise TypeError('%r is not an integer type' % value)
    if value < self._min_value or value > self._max_value:
      raise OverflowError('%r is not in the range [%d, %d]' %
                          (value, self._min_value, self._max_value))
    return value


class FloatType(NumericType):
  """Type object for floating point number types."""

  def Convert(self, value):
    if value is None:
      raise TypeError('None is not an floating point number.')
    if not isinstance(value, (int, long, float)):
      raise TypeError('%r is not a numeric type' % value)
    return float(value)


class PointerType(SerializableType):
  """Base Type object for pointers."""

  def __init__(self, nullable=False):
    SerializableType.__init__(self, 'Q')
    self.nullable = nullable

  def Serialize(self, value, data_offset, data, handle_offset):
    if value is None and not self.nullable:
      raise serialization.SerializationException(
          'Trying to serialize null for non nullable type.')
    if value is None:
      return (0, [])
    return self.SerializePointer(value, data_offset, data, handle_offset)

  def Deserialize(self, value, context):
    if value == 0:
      if not self.nullable:
        raise serialization.DeserializationException(
            'Trying to deserialize null for non nullable type.')
      return None
    if value % 8 != 0:
      raise serialization.DeserializationException(
          'Pointer alignment is incorrect.')
    sub_context = context.GetSubContext(value)
    if len(sub_context.data) < serialization.HEADER_STRUCT.size:
      raise serialization.DeserializationException(
          'Available data too short to contain header.')
    (size, nb_elements) = serialization.HEADER_STRUCT.unpack_from(
        sub_context.data)
    if len(sub_context.data) < size or size < serialization.HEADER_STRUCT.size:
      raise serialization.DeserializationException('Header size is incorrect.')
    sub_context.ClaimMemory(0, size)
    return self.DeserializePointer(size, nb_elements, sub_context)

  def SerializePointer(self, value, data_offset, data, handle_offset):
    """Serialize the not null value."""
    raise NotImplementedError()

  def DeserializePointer(self, size, nb_elements, context):
    raise NotImplementedError()


class StringType(PointerType):
  """
  Type object for strings.

  Strings are represented as unicode, and the conversion is done using the
  default encoding if a string instance is used.
  """

  def __init__(self, nullable=False):
    PointerType.__init__(self, nullable)
    self._array_type = NativeArrayType('B', nullable)

  def Convert(self, value):
    if value is None or isinstance(value, unicode):
      return value
    if isinstance(value, str):
      return unicode(value)
    raise TypeError('%r is not a string' % value)

  def SerializePointer(self, value, data_offset, data, handle_offset):
    string_array = array.array('b')
    string_array.fromstring(value.encode('utf8'))
    return self._array_type.SerializeArray(
        string_array, data_offset, data, handle_offset)

  def DeserializePointer(self, size, nb_elements, context):
    string_array = self._array_type.DeserializeArray(size, nb_elements, context)
    return unicode(string_array.tostring(), 'utf8')


class BaseHandleType(SerializableType):
  """Type object for handles."""

  def __init__(self, nullable=False):
    SerializableType.__init__(self, 'i')
    self.nullable = nullable

  def Serialize(self, value, data_offset, data, handle_offset):
    handle = self.ToHandle(value)
    if not handle.IsValid() and not self.nullable:
      raise serialization.SerializationException(
          'Trying to serialize null for non nullable type.')
    if not handle.IsValid():
      return (-1, [])
    return (handle_offset, [handle])

  def Deserialize(self, value, context):
    if value == -1:
      if not self.nullable:
        raise serialization.DeserializationException(
            'Trying to deserialize null for non nullable type.')
      return self.FromHandle(mojo_system.Handle())
    return self.FromHandle(context.ClaimHandle(value))

  def FromHandle(self, handle):
    raise NotImplementedError()

  def ToHandle(self, value):
    raise NotImplementedError()


class HandleType(BaseHandleType):
  """Type object for handles."""

  def Convert(self, value):
    if value is None:
      return mojo_system.Handle()
    if not isinstance(value, mojo_system.Handle):
      raise TypeError('%r is not a handle' % value)
    return value

  def FromHandle(self, handle):
    return handle

  def ToHandle(self, value):
    return value


class InterfaceRequestType(BaseHandleType):
  """Type object for interface requests."""

  def Convert(self, value):
    if value is None:
      return reflection.InterfaceRequest(mojo_system.Handle())
    if not isinstance(value, reflection.InterfaceRequest):
      raise TypeError('%r is not an interface request' % value)
    return value

  def FromHandle(self, handle):
    return reflection.InterfaceRequest(handle)

  def ToHandle(self, value):
    return value.PassMessagePipe()


class InterfaceType(BaseHandleType):
  """Type object for interfaces."""

  def __init__(self, interface_getter, nullable=False):
    BaseHandleType.__init__(self, nullable)
    self._interface_getter = interface_getter
    self._interface = None

  def Convert(self, value):
    if value is None or isinstance(value, self.interface):
      return value
    raise TypeError('%r is not an instance of ' % self.interface)

  @property
  def interface(self):
    if not self._interface:
      self._interface = self._interface_getter()
    return self._interface

  def FromHandle(self, handle):
    if handle.IsValid():
      return self.interface.manager.Proxy(handle)
    return None

  def ToHandle(self, value):
    if not value:
      return mojo_system.Handle()
    if isinstance(value, reflection.InterfaceProxy):
      return value.manager.PassMessagePipe()
    pipe = mojo_system.MessagePipe()
    self.interface.manager.Bind(value, pipe.handle0)
    return pipe.handle1


class BaseArrayType(PointerType):
  """Abstract Type object for arrays."""

  def __init__(self, nullable=False, length=0):
    PointerType.__init__(self, nullable)
    self.length = length

  def SerializePointer(self, value, data_offset, data, handle_offset):
    if self.length != 0 and len(value) != self.length:
      raise serialization.SerializationException('Incorrect array size')
    return self.SerializeArray(value, data_offset, data, handle_offset)

  def SerializeArray(self, value, data_offset, data, handle_offset):
    """Serialize the not null array."""
    raise NotImplementedError()

  def DeserializePointer(self, size, nb_elements, context):
    if self.length != 0 and nb_elements != self.length:
      raise serialization.DeserializationException('Incorrect array size')
    if (size <
        serialization.HEADER_STRUCT.size + self.SizeForLength(nb_elements)):
      raise serialization.DeserializationException('Incorrect array size')
    return self.DeserializeArray(size, nb_elements, context)

  def DeserializeArray(self, size, nb_elements, context):
    raise NotImplementedError()

  def SizeForLength(self, nb_elements):
    raise NotImplementedError()


class BooleanArrayType(BaseArrayType):

  def __init__(self, nullable=False, length=0):
    BaseArrayType.__init__(self, nullable, length)
    self._array_type = NativeArrayType('B', nullable)

  def Convert(self, value):
    if value is None:
      return value
    return [TYPE_BOOL.Convert(x) for x in value]

  def SerializeArray(self, value, data_offset, data, handle_offset):
    groups = [value[i:i+8] for i in range(0, len(value), 8)]
    converted = array.array('B', [_ConvertBooleansToByte(x) for x in groups])
    return _SerializeNativeArray(converted, data_offset, data, len(value))

  def DeserializeArray(self, size, nb_elements, context):
    converted = self._array_type.DeserializeArray(size, nb_elements, context)
    elements = list(itertools.islice(
        itertools.chain.from_iterable(
            [_ConvertByteToBooleans(x, 8) for x in converted]),
        0,
        nb_elements))
    return elements

  def SizeForLength(self, nb_elements):
    return (nb_elements + 7) // 8


class GenericArrayType(BaseArrayType):
  """Type object for arrays of pointers."""

  def __init__(self, sub_type, nullable=False, length=0):
    BaseArrayType.__init__(self, nullable, length)
    assert isinstance(sub_type, SerializableType)
    self.sub_type = sub_type

  def Convert(self, value):
    if value is None:
      return value
    return [self.sub_type.Convert(x) for x in value]

  def SerializeArray(self, value, data_offset, data, handle_offset):
    size = (serialization.HEADER_STRUCT.size +
            self.sub_type.GetByteSize() * len(value))
    data_end = len(data)
    position = len(data) + serialization.HEADER_STRUCT.size
    data.extend(bytearray(size +
                          serialization.NeededPaddingForAlignment(size)))
    returned_handles = []
    to_pack = []
    for item in value:
      (new_data, new_handles) = self.sub_type.Serialize(
          item,
          len(data) - position,
          data,
          handle_offset + len(returned_handles))
      to_pack.append(new_data)
      returned_handles.extend(new_handles)
      position = position + self.sub_type.GetByteSize()
    serialization.HEADER_STRUCT.pack_into(data, data_end, size, len(value))
    struct.pack_into('%d%s' % (len(value), self.sub_type.GetTypeCode()),
                     data,
                     data_end + serialization.HEADER_STRUCT.size,
                     *to_pack)
    return (data_offset, returned_handles)

  def DeserializeArray(self, size, nb_elements, context):
    values = struct.unpack_from(
        '%d%s' % (nb_elements, self.sub_type.GetTypeCode()),
        buffer(context.data, serialization.HEADER_STRUCT.size))
    result = []
    sub_context = context.GetSubContext(serialization.HEADER_STRUCT.size)
    for value in values:
      result.append(self.sub_type.Deserialize(
          value,
          sub_context))
      sub_context = sub_context.GetSubContext(self.sub_type.GetByteSize())
    return result

  def SizeForLength(self, nb_elements):
    return nb_elements * self.sub_type.GetByteSize();


class NativeArrayType(BaseArrayType):
  """Type object for arrays of native types."""

  def __init__(self, typecode, nullable=False, length=0):
    BaseArrayType.__init__(self, nullable, length)
    self.array_typecode = typecode
    self.element_size = struct.calcsize('<%s' % self.array_typecode)

  def Convert(self, value):
    if value is None:
      return value
    if (isinstance(value, array.array) and
        value.array_typecode == self.array_typecode):
      return value
    return array.array(self.array_typecode, value)

  def SerializeArray(self, value, data_offset, data, handle_offset):
    return _SerializeNativeArray(value, data_offset, data, len(value))

  def DeserializeArray(self, size, nb_elements, context):
    result = array.array(self.array_typecode)
    result.fromstring(buffer(context.data,
                             serialization.HEADER_STRUCT.size,
                             size - serialization.HEADER_STRUCT.size))
    return result

  def SizeForLength(self, nb_elements):
    return nb_elements * self.element_size


class StructType(PointerType):
  """Type object for structs."""

  def __init__(self, struct_type_getter, nullable=False):
    PointerType.__init__(self)
    self._struct_type_getter = struct_type_getter
    self._struct_type = None
    self.nullable = nullable

  @property
  def struct_type(self):
    if not self._struct_type:
      self._struct_type = self._struct_type_getter()
    return self._struct_type

  def Convert(self, value):
    if value is None or isinstance(value, self.struct_type):
      return value
    raise TypeError('%r is not an instance of %r' % (value, self.struct_type))

  def GetDefaultValue(self, value):
    if value:
      return self.struct_type()
    return None

  def SerializePointer(self, value, data_offset, data, handle_offset):
    (new_data, new_handles) = value.Serialize(handle_offset)
    data.extend(new_data)
    return (data_offset, new_handles)

  def DeserializePointer(self, size, nb_elements, context):
    return self.struct_type.Deserialize(context)


class MapType(SerializableType):
  """Type objects for maps."""

  def __init__(self, key_type, value_type, nullable=False):
    self._key_type = key_type
    self._value_type = value_type
    dictionary = {
      '__metaclass__': reflection.MojoStructType,
      '__module__': __name__,
      'DESCRIPTOR': {
        'fields': [
          SingleFieldGroup('keys', MapType._GetArrayType(key_type), 0, 1),
          SingleFieldGroup('values', MapType._GetArrayType(value_type), 1, 2),
        ],
      }
    }
    self.struct = reflection.MojoStructType('MapStruct', (object,), dictionary)
    self.struct_type = StructType(lambda: self.struct, nullable)
    SerializableType.__init__(self, self.struct_type.typecode)

  def Convert(self, value):
    if value is None:
      return value
    if isinstance(value, dict):
      return dict([(self._key_type.Convert(x), self._value_type.Convert(y)) for
                   x, y in value.iteritems()])
    raise TypeError('%r is not a dictionary.')

  def Serialize(self, value, data_offset, data, handle_offset):
    s = None
    if value:
      keys, values = [], []
      for key, value in value.iteritems():
        keys.append(key)
        values.append(value)
      s = self.struct(keys=keys, values=values)
    return self.struct_type.Serialize(s, data_offset, data, handle_offset)

  def Deserialize(self, value, context):
    s = self.struct_type.Deserialize(value, context)
    if s:
      if len(s.keys) != len(s.values):
        raise serialization.DeserializationException(
            'keys and values do not have the same length.')
      return dict(zip(s.keys, s.values))
    return None

  @staticmethod
  def _GetArrayType(t):
    if t == TYPE_BOOL:
      return BooleanArrayType()
    else:
      return GenericArrayType(t)


TYPE_BOOL = BooleanType()

TYPE_INT8 = IntegerType('b')
TYPE_INT16 = IntegerType('h')
TYPE_INT32 = IntegerType('i')
TYPE_INT64 = IntegerType('q')

TYPE_UINT8 = IntegerType('B')
TYPE_UINT16 = IntegerType('H')
TYPE_UINT32 = IntegerType('I')
TYPE_UINT64 = IntegerType('Q')

TYPE_FLOAT = FloatType('f')
TYPE_DOUBLE = FloatType('d')

TYPE_STRING = StringType()
TYPE_NULLABLE_STRING = StringType(True)

TYPE_HANDLE = HandleType()
TYPE_NULLABLE_HANDLE = HandleType(True)

TYPE_INTERFACE_REQUEST = InterfaceRequestType()
TYPE_NULLABLE_INTERFACE_REQUEST = InterfaceRequestType(True)


class FieldDescriptor(object):
  """Describes a field in a generated struct."""

  def __init__(self, name, field_type, index, version, default_value=None):
    self.name = name
    self.field_type = field_type
    self.version = version
    self.index = index
    self._default_value = default_value

  def GetDefaultValue(self):
    return self.field_type.GetDefaultValue(self._default_value)


class FieldGroup(object):
  """
  Describe a list of field in the generated struct that must be
  serialized/deserialized together.
  """
  def __init__(self, descriptors):
    self.descriptors = descriptors

  def GetDescriptors(self):
    return self.descriptors

  def GetTypeCode(self):
    raise NotImplementedError()

  def GetByteSize(self):
    raise NotImplementedError()

  def GetMinVersion(self):
    raise NotImplementedError()

  def GetMaxVersion(self):
    raise NotImplementedError()

  def Serialize(self, obj, data_offset, data, handle_offset):
    raise NotImplementedError()

  def Deserialize(self, value, context):
    raise NotImplementedError()

  def Filter(self, version):
    raise NotImplementedError()


class SingleFieldGroup(FieldGroup, FieldDescriptor):
  """A FieldGroup that contains a single FieldDescriptor."""

  def __init__(self, name, field_type, index, version, default_value=None):
    FieldDescriptor.__init__(
        self, name, field_type, index, version, default_value)
    FieldGroup.__init__(self, [self])

  def GetTypeCode(self):
    return self.field_type.GetTypeCode()

  def GetByteSize(self):
    return self.field_type.GetByteSize()

  def GetMinVersion(self):
    return self.version

  def GetMaxVersion(self):
    return self.version

  def Serialize(self, obj, data_offset, data, handle_offset):
    value = getattr(obj, self.name)
    return self.field_type.Serialize(value, data_offset, data, handle_offset)

  def Deserialize(self, value, context):
    entity = self.field_type.Deserialize(value, context)
    return { self.name: entity }

  def Filter(self, version):
    return self


class BooleanGroup(FieldGroup):
  """A FieldGroup to pack booleans."""
  def __init__(self, descriptors):
    FieldGroup.__init__(self, descriptors)
    self.min_version = min([descriptor.version  for descriptor in descriptors])
    self.max_version = max([descriptor.version  for descriptor in descriptors])

  def GetTypeCode(self):
    return 'B'

  def GetByteSize(self):
    return 1

  def GetMinVersion(self):
    return self.min_version

  def GetMaxVersion(self):
    return self.max_version

  def Serialize(self, obj, data_offset, data, handle_offset):
    value = _ConvertBooleansToByte(
        [getattr(obj, field.name) for field in self.GetDescriptors()])
    return (value, [])

  def Deserialize(self, value, context):
    values =  itertools.izip_longest([x.name for x in self.descriptors],
                                      _ConvertByteToBooleans(value),
                                     fillvalue=False)
    return dict(values)

  def Filter(self, version):
    return BooleanGroup(
        filter(lambda d: d.version <= version, self.descriptors))


def _SerializeNativeArray(value, data_offset, data, length):
  data_size = len(data)
  data.extend(bytearray(serialization.HEADER_STRUCT.size))
  data.extend(buffer(value))
  data_length = len(data) - data_size
  data.extend(bytearray(serialization.NeededPaddingForAlignment(data_length)))
  serialization.HEADER_STRUCT.pack_into(data, data_size, data_length, length)
  return (data_offset, [])


def _ConvertBooleansToByte(booleans):
  """Pack a list of booleans into an integer."""
  return reduce(lambda x, y: x * 2 + y, reversed(booleans), 0)


def _ConvertByteToBooleans(value, min_size=0):
  """Unpack an integer into a list of booleans."""
  res = []
  while value:
    res.append(bool(value&1))
    value = value / 2
  res.extend([False] * (min_size - len(res)))
  return res
