#
#

# Copyright (C) 2012 Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""Module for object related utils."""


#: Supported container types for serialization/de-serialization (must be a
#: tuple as it's used as a parameter for C{isinstance})
_SEQUENCE_TYPES = (list, tuple, set, frozenset)


class AutoSlots(type):
  """Meta base class for __slots__ definitions.

  """
  def __new__(mcs, name, bases, attrs):
    """Called when a class should be created.

    @param mcs: The meta class
    @param name: Name of created class
    @param bases: Base classes
    @type attrs: dict
    @param attrs: Class attributes

    """
    assert "__slots__" not in attrs, \
      "Class '%s' defines __slots__ when it should not" % name

    attrs["__slots__"] = mcs._GetSlots(attrs)

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

  @classmethod
  def _GetSlots(mcs, attrs):
    """Used to get the list of defined slots.

    @param attrs: The attributes of the class

    """
    raise NotImplementedError


class ValidatedSlots(object):
  """Sets and validates slots.

  """
  __slots__ = []

  def __init__(self, **kwargs):
    """Constructor for BaseOpCode.

    The constructor takes only keyword arguments and will set
    attributes on this object based on the passed arguments. As such,
    it means that you should not pass arguments which are not in the
    __slots__ attribute for this class.

    """
    slots = self.GetAllSlots()
    for (key, value) in kwargs.items():
      if key not in slots:
        raise TypeError("Object %s doesn't support the parameter '%s'" %
                        (self.__class__.__name__, key))
      setattr(self, key, value)

  @classmethod
  def GetAllSlots(cls):
    """Compute the list of all declared slots for a class.

    """
    slots = []
    for parent in cls.__mro__:
      slots.extend(getattr(parent, "__slots__", []))
    return slots

  def Validate(self):
    """Validates the slots.

    This method must be implemented by the child classes.

    """
    raise NotImplementedError


def ContainerToDicts(container):
  """Convert the elements of a container to standard Python types.

  This method converts a container with elements to standard Python types. If
  the input container is of the type C{dict}, only its values are touched.
  Those values, as well as all elements of input sequences, must support a
  C{ToDict} method returning a serialized version.

  @type container: dict or sequence (see L{_SEQUENCE_TYPES})

  """
  if isinstance(container, dict):
    ret = dict([(k, v.ToDict()) for k, v in container.items()])
  elif isinstance(container, _SEQUENCE_TYPES):
    ret = [elem.ToDict() for elem in container]
  else:
    raise TypeError("Unknown container type '%s'" % type(container))

  return ret


def ContainerFromDicts(source, c_type, e_type):
  """Convert a container from standard python types.

  This method converts a container with standard Python types to objects. If
  the container is a dict, we don't touch the keys, only the values.

  @type source: None, dict or sequence (see L{_SEQUENCE_TYPES})
  @param source: Input data
  @type c_type: type class
  @param c_type: Desired type for returned container
  @type e_type: element type class
  @param e_type: Item type for elements in returned container (must have a
    C{FromDict} class method)

  """
  if not isinstance(c_type, type):
    raise TypeError("Container type '%s' is not a type" % type(c_type))

  if source is None:
    source = c_type()

  if c_type is dict:
    ret = dict([(k, e_type.FromDict(v)) for k, v in source.items()])
  elif c_type in _SEQUENCE_TYPES:
    ret = c_type(map(e_type.FromDict, source))
  else:
    raise TypeError("Unknown container type '%s'" % c_type)

  return ret
