# Lint as: python2, python3
# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import inspect
import logging
import six
import sys


TYPE_KEY = 'xmlrpc_struct_type_key'


def deserialize(serialized, module=None):
    """Deserialize an XmlRpcStruct.

    Because Python XMLRPC doesn't understand anything more than basic
    types, we're forced to reinvent type serialization.  This is one way
    to do it.

    This function looks at the constructor and figures out what subset of
    |serialized| will be accepted as arguments.

    @param serialized dict representing a serialized XmlRpcStruct.
    @param module module object to pull classes from.  Defaults to
            this file.
    @return an XmlRpcStruct object built from |serialized|.

    """
    if TYPE_KEY not in serialized:
        logging.error('Failed to deserialize XmlRpcStruct because of '
                      'missing type.')
        logging.error('Got serialized object: %r', serialized)
        return None

    if module is None:
        module = sys.modules[__name__]
    klass = getattr(module, serialized[TYPE_KEY])
    constructor_args = inspect.getargspec(klass.__init__)
    optional_args = []
    if constructor_args.defaults:
        # Valid args should now be a list of all the parameters that have
        # default values.
        optional_args = constructor_args.args[-len(constructor_args.defaults):]
        # skip to argument 1 because the first argument is always |self|.
        required_args = constructor_args.args[1:-len(constructor_args.defaults)]
    args = []
    for arg in required_args:
        if arg not in serialized:
            logging.error('Failed to find non-keyword argument %s', arg)
            return None

        args.append(serialized[arg])
    kwargs = dict([k_v for k_v in six.iteritems(serialized) if k_v[0] in optional_args])
    logging.debug('Constructing %s object with args=%r, kwargs=%r',
                  serialized[TYPE_KEY], args, kwargs)
    return klass(*args, **kwargs)


class XmlRpcStruct(object):
    """Enables deserialization by injecting the proper class type.

    To make deserilization work for you, write a constructor like:

    def __init__(self, arg1, arg2='foo'):
        # It is important that self.arg1 = arg1.  Otherwise arguments
        # won't be sent over the wire correctly.
        self.arg1 = arg1
        self.arg2 = arg2

    Serialization happens automatically when using XMLRPC proxies, since
    Python's XMLRPC framework will take all fields from your object and drop
    them into a dict to go over the wire.  To deserialize your object on the
    other side, call deserialize() and pass in the module defining the
    requisite class.

    serialize() is provided to allow objects to fake that they are XMLRPC
    proxies.

    """

    def __init__(self):
        super(XmlRpcStruct, self).__init__()
        setattr(self, TYPE_KEY, self.__class__.__name__)


    def serialize(self):
        """@return dict of object fields."""
        return self.__dict__
