# Copyright 2017 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.
"""This module provides a base class with a main feature to (de)serialize data.

The base class supports:
  * Serializable: can be serialized into de-serialized from a dict.
  * Type validation: define attributes with types, and is custom-validatable.
        None is an accepted value for all types.
  * Compositable: one object can contain other objects derived from the class.

One main usage of the base class is to define structured objects that are to be
serialized, transferred among different parts of a system or over http, and then
deserialized back to python objects.

A subclass should define "public" class-level attributes in the class instead of
within the constructor for an instance (if an instance changes the value of a
class-level attribute, the change is scoped to the instance itself and doesn't
impact the definition in the class), and those attributes will be serialized to
a dict or deserialized from a dict. The constructor in the subclass should
accept keyword parameters only, it must absorb those that are not defined
attributes and pass the remaining ones to the base class StructuredObject.

Examples:
1. Set values to an serializable object:
  class MyObjectA(StructuredObject):
    a = int
    b = str
    _unused = 'Private class attributes are allowed :), but not serialized :('

    def __init__(self, param='', **kwargs):
      super(MyObjectA, self).__init__(**kwargs)
      self._ok = 'Private instance attributes allowed :), but not serialized :('
      self._param = param
      # Uncomment line below will cause an Exception.
      # self.not_ok = 'Public instance attributes are not allowed :('

    @property
    def unused(self):
      return 'All properties are not serialized'

  There are two way to set the values of defined attributes:
      obj_a = MyObjectA()
      obj_a.a = 3
      obj_a.b = 'a string'
  or just simply:
      obj_a = MyObjectA(a=3, b='a string')

2. ToSerializable an object and deserialize:
  obj_a = MyObjectA(a=3, b='a string')
  data = obj_a.ToSerializable()
  assert data == {'a': 3, 'b': 'a string'}
  obj_a_copy = MyObjectA.FromSerializable(data)
  assert obj_a.a == obj_a_copy.a
  assert obj_a.b == obj_a_copy.b

3. Compositable:
  class MyObjectB(StructuredObject):
    v = dict
    o = MyObjectA

  obj_b = MyObjectB.FromSerializable(
      {'v': {'key': 'value'}, 'o': {'a': 3, 'b': 'a string'}})
  # obj_b = MyObjectB(v={'key': 'value'}, o=obj_a)
  assert obj_b.v == {'key': 'value'}
  assert obj_b.o.a == 3
  assert obj_b.o.b == 'a string'

4. Use customized type validation function.

  class Future1(object):
    pass

  class Future2(object):
    pass

  class MyObjectC(StructuredObject):
    v1 = dict
    v2 = list

  def ValidateTypes(attribute_name, attribute_value):
    # input: attribute name and its value.
    # output: bool. True if valid; otherwise False.
    valid_types = {
        'v1': Future1,
        'v2': Future2,
    }
    return isinstance(attribute_value, _Valid_types[attribute_name])

  obj_c = MyObjectC(type_validation_func=ValidateTypes,
                    v1=Future1(),
                    v2=Future2())
  assert isinstance(obj_c.v1, Future1), 'this should pass'
  assert isinstance(obj_c.v2, Future2), 'this should pass'
"""

from collections import MutableMapping
from collections import MutableSequence
import logging
import types


class DeserializationError(Exception):
  pass


class BaseSerializableObject(object):
  """This is the base class of StructuredObject, TypedDict and TypedList."""
  # Set this to true to allow deserializing from objects with unrecognized
  # attributes (and ignore them). Otherwise, deserializing will fail normally.
  _ignore_unknown_attributes = False

  def ToSerializable(self):
    """Returns a dict or a list which all items are serialized."""
    raise NotImplementedError

  @classmethod
  def FromSerializable(cls, data):
    """Deserialized given data and returns an instance of this class."""
    raise NotImplementedError

  def __eq__(self, other):
    if not isinstance(other, self.__class__):
      return False
    return self.ToSerializable() == other.ToSerializable()


class StructuredObject(BaseSerializableObject):

  def __init__(self, type_validation_func=None, **kwargs):
    """Constructor.

    Args:
      type_validation_func (function): A customized function to validate whether
          a given attribute value is accepted or not. Its input is the attribute
          name and value, and its output is a True/False to indicate whether the
          value is accepted or not accepted respectively.
      kwargs (dict): All other keyword parameters are used to set values of
          defined attributes.
    """
    self._type_validation_func = type_validation_func
    self._data = {}
    for name, value in kwargs.iteritems():
      setattr(self, name, value)

  def __setattr__(self, name, value):
    """Intercepts attribute settings and validates types of attribute values."""
    if name.startswith('_'):  # Allow private instance attributes.
      object.__setattr__(self, name, value)
      return

    attribute_type = self._GetDefinedAttributes().get(name)
    assert attribute_type is not None, '%s.%s is undefined' % (
        self.__class__.__name__, name)
    if value is not None:
      if not self._type_validation_func:
        assert isinstance(
            value,
            attribute_type), ('%s.%s: expected type %s, but got %s' %
                              (self.__class__.__name__, name,
                               attribute_type.__name__, type(value).__name__))
      elif not isinstance(value, attribute_type):
        assert self._type_validation_func(name, value), (
            'Value of type %s for %s.%s failed a customized type validation' %
            (type(value).__name__, self.__class__.__name__, name))
    self._data[name] = value

  def __getattribute__(self, name):
    """Intercepts attribute access and returns values of defined attributes."""
    # __getattr__ won't work because dynamically-defined attributes are
    # expected to be in the class so that they are directly accessible and
    # __getattr__ won't be triggered.
    # __getattribute__ is always triggered upon accessing any attribute,
    # function, or method with a class instance, e.g. self.__class__ or
    # self._GetDefinedAttributes.
    # However, this function needs to access _GetDefinedAttributes with an
    # instance of the subclass. So we have to handle invocation of
    # _GetDefinedAttributes first to avoid infinite recursive invocation between
    # _GetDefinedAttributes and __getattribute__.
    if name.startswith('_'):
      return object.__getattribute__(self, name)
    if name in self._GetDefinedAttributes():
      return self._data[name]
    return object.__getattribute__(self, name)

  @classmethod
  def _GetDefinedAttributes(cls):
    """Returns a map from defined attributes to their types.

    Args:
      cls (class): The subclass.

    Returns:
      A dict from defined attributes to their types.
    """
    cache_name = '_%s.%s._dynamic_definitions' % (cls.__module__, cls.__name__)
    if not hasattr(cls, cache_name):
      d = {}
      for name in dir(cls):
        if name.startswith('_'):
          continue  # Ignore private attributes.
        value = getattr(cls, name)
        if isinstance(value, property):
          continue  # Ignore properties.
        if isinstance(value, (types.MethodType, types.FunctionType)):
          continue  # Ignore functions and methods.
        d[name] = value
      setattr(cls, cache_name, d)
    return getattr(cls, cache_name)

  def ToSerializable(self):
    """Returns a dict into which all defined attributes are serialized."""
    data = {}
    defined_attributes = self._GetDefinedAttributes()
    for name, value_type in defined_attributes.iteritems():
      assert name in self._data, '%s.%s is not set' % (self.__class__.__name__,
                                                       name)
      value = self._data[name]
      if (value is not None and
          issubclass(value_type, BaseSerializableObject) and
          not (self._type_validation_func and
               self._type_validation_func(name, value))):
        # Only encode the value if its defined type is StructuredObject AND
        # The customized type validation function doesn't accept its value.
        # If the validation function accepts the value, keep the value as is for
        # the caller code to do some customized processing later.
        value = value.ToSerializable()
      data[name] = value
    return data

  def __repr__(self):
    """Returns a string that represents this class instance."""
    return '%s(%r)' % (self.__class__.__name__, self.ToSerializable())

  def __eq__(self, other):
    """Returns True if this object is equal to the given one."""
    if not isinstance(other, self.__class__):
      return False
    for name in self._GetDefinedAttributes():
      if not getattr(self, name) == getattr(other, name):
        return False
    return True

  def __ne__(self, other):
    """Returns True if this object is not equal to the given one."""
    return not self == other

  @classmethod
  def FromSerializable(cls, data):
    """Deserializes the given data and returns an instance of this class.

    Args:
      cls  (class): The subclass.
      data (dict): The dict mapping from defined attributes to their values.

    Returns:
      An instance of the given class with attributes set to the given data.
    """
    if data is None:
      return data

    if not isinstance(data, dict):
      raise DeserializationError(
          'Expecting a dict, but got %s' % type(data).__name__)
    defined_attributes = cls._GetDefinedAttributes()
    undefined_attributes = set(data.keys()) - set(defined_attributes.keys())
    try:
      if len(undefined_attributes) != 0:
        raise DeserializationError(
            '%s not defined in %s' % (','.join(undefined_attributes),
                                      cls.__name__))
    except DeserializationError:
      # For error reporting to catch this log record (and notify the team), the
      # logging has to happen inside an except block s.t. logging module can tag
      # the log with a stacktrace, required by strackdriver error reporting.
      logging.exception('DeserializationError')
      if not cls._ignore_unknown_attributes:
        raise

    instance = cls()
    for name, value_type in defined_attributes.iteritems():
      if name not in data:
        setattr(instance, name, None)
        logging.warning('Assigned None to %s.%s as it is missing in %r',
                        cls.__name__, name, data)
      else:
        value = data[name]

        if issubclass(value_type, BaseSerializableObject):
          value = value_type.FromSerializable(value)

        setattr(instance, name, value)
    return instance


def _CheckType(class_name, item_type, value):
  if not isinstance(value, item_type):
    raise Exception('%s only accepts type %s as values, but got %s.' %
                    (class_name, item_type.__name__, type(value).__name__))


class TypedDict(MutableMapping, BaseSerializableObject):
  """A dict-like object can only accept specific type of values."""
  _value_type = type(None)

  def __init__(self):
    self._dict = {}

  def __getitem__(self, key):
    return self._dict[key]

  def __setitem__(self, key, value):
    _CheckType(self.__class__.__name__, self._value_type, value)
    self._dict[key] = value

  def __delitem__(self, key):
    del self._dict[key]

  def __iter__(self):
    return iter(self._dict)

  def __len__(self):
    return len(self._dict)

  def ToSerializable(self):
    result = {}
    if issubclass(self._value_type, BaseSerializableObject):
      # Serialize sub objects as well.
      for key, value in self._dict.iteritems():
        result[key] = value.ToSerializable()
    else:
      result.update(self._dict)

    return result

  @classmethod
  def FromSerializable(cls, data):
    if data is None:
      return None

    instance = cls()
    if issubclass(instance._value_type, BaseSerializableObject):
      for key, value in data.iteritems():
        instance._dict[key] = instance._value_type.FromSerializable(value)
    else:
      instance._dict.update(data)

    return instance


class TypedList(MutableSequence, BaseSerializableObject):
  """A list-like object can only accept specific type of elements."""

  _element_type = type(None)

  def __init__(self):
    self._list = []

  def __getitem__(self, index):
    return self._list[index]

  def __setitem__(self, index, value):
    _CheckType(self.__class__.__name__, self._element_type, value)
    self._list[index] = value

  def __delitem__(self, index):
    del self._list[index]

  def __len__(self):
    return len(self._list)

  def insert(self, index, value):
    _CheckType(self.__class__.__name__, self._element_type, value)
    self._list.insert(index, value)

  def ToSerializable(self):
    result = []
    if issubclass(self._element_type, BaseSerializableObject):
      # Serialize sub objects as well.
      for element in self._list:
        result.append(element.ToSerializable())
    else:
      result.extend(self._list)

    return result

  @classmethod
  def FromSerializable(cls, data):
    if data is None:
      return None

    instance = cls()
    if issubclass(instance._element_type, BaseSerializableObject):
      for value in data:
        instance._list.append(instance._element_type.FromSerializable(value))
    else:
      instance._list.extend(data)

    return instance
