#!/usr/bin/env python
#
# Copyright 2010 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""JSON support for message types.

Public classes:
  MessageJSONEncoder: JSON encoder for message objects.

Public functions:
  encode_message: Encodes a message in to a JSON string.
  decode_message: Merge from a JSON string in to a message.
"""
import six

__author__ = 'rafek@google.com (Rafe Kaplan)'

import base64
import binascii
import logging

from . import message_types
from . import messages
from . import util

__all__ = [
    'ALTERNATIVE_CONTENT_TYPES',
    'CONTENT_TYPE',
    'MessageJSONEncoder',
    'encode_message',
    'decode_message',
    'ProtoJson',
]


def _load_json_module():
  """Try to load a valid json module.

  There are more than one json modules that might be installed.  They are
  mostly compatible with one another but some versions may be different.
  This function attempts to load various json modules in a preferred order.
  It does a basic check to guess if a loaded version of json is compatible.

  Returns:
    Compatible json module.

  Raises:
    ImportError if there are no json modules or the loaded json module is
      not compatible with ProtoRPC.
  """
  first_import_error = None
  for module_name in ['json',
                      'simplejson']:
    try:
      module = __import__(module_name, {}, {}, 'json')
      if not hasattr(module, 'JSONEncoder'):
        message = ('json library "%s" is not compatible with ProtoRPC' %
                   module_name)
        logging.warning(message)
        raise ImportError(message)
      else:
        return module
    except ImportError as err:
      if not first_import_error:
        first_import_error = err

  logging.error('Must use valid json library (Python 2.6 json or simplejson)')
  raise first_import_error
json = _load_json_module()


# TODO: Rename this to MessageJsonEncoder.
class MessageJSONEncoder(json.JSONEncoder):
  """Message JSON encoder class.

  Extension of JSONEncoder that can build JSON from a message object.
  """

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

    Args:
      protojson_protocol: ProtoJson instance.
    """
    super(MessageJSONEncoder, self).__init__(**kwargs)
    self.__protojson_protocol = protojson_protocol or ProtoJson.get_default()

  def default(self, value):
    """Return dictionary instance from a message object.

    Args:
    value: Value to get dictionary for.  If not encodable, will
      call superclasses default method.
    """
    if isinstance(value, messages.Enum):
      return str(value)

    if six.PY3 and isinstance(value, bytes):
      return value.decode('utf8')

    if isinstance(value, messages.Message):
      result = {}
      for field in value.all_fields():
        item = value.get_assigned_value(field.name)
        if item not in (None, [], ()):
          result[field.name] = self.__protojson_protocol.encode_field(
             field, item)
      # Handle unrecognized fields, so they're included when a message is
      # decoded then encoded.
      for unknown_key in value.all_unrecognized_fields():
        unrecognized_field, _ = value.get_unrecognized_field_info(unknown_key)
        result[unknown_key] = unrecognized_field
      return result
    else:
      return super(MessageJSONEncoder, self).default(value)


class ProtoJson(object):
  """ProtoRPC JSON implementation class.

  Implementation of JSON based protocol used for serializing and deserializing
  message objects.  Instances of remote.ProtocolConfig constructor or used with
  remote.Protocols.add_protocol.  See the remote.py module for more details.
  """

  CONTENT_TYPE = 'application/json'
  ALTERNATIVE_CONTENT_TYPES = [
      'application/x-javascript',
      'text/javascript',
      'text/x-javascript',
      'text/x-json',
      'text/json',
  ]

  def encode_field(self, field, value):
    """Encode a python field value to a JSON value.

    Args:
      field: A ProtoRPC field instance.
      value: A python value supported by field.

    Returns:
      A JSON serializable value appropriate for field.
    """
    if isinstance(field, messages.BytesField):
      if field.repeated:
        value = [base64.b64encode(byte) for byte in value]
      else:
        value = base64.b64encode(value)
    elif isinstance(field, message_types.DateTimeField):
      # DateTimeField stores its data as a RFC 3339 compliant string.
      if field.repeated:
        value = [i.isoformat() for i in value]
      else:
        value = value.isoformat()
    return value

  def encode_message(self, message):
    """Encode Message instance to JSON string.

    Args:
      Message instance to encode in to JSON string.

    Returns:
      String encoding of Message instance in protocol JSON format.

    Raises:
      messages.ValidationError if message is not initialized.
    """
    message.check_initialized()

    return json.dumps(message, cls=MessageJSONEncoder, protojson_protocol=self)

  def decode_message(self, message_type, encoded_message):
    """Merge JSON structure to Message instance.

    Args:
      message_type: Message to decode data to.
      encoded_message: JSON encoded version of message.

    Returns:
      Decoded instance of message_type.

    Raises:
      ValueError: If encoded_message is not valid JSON.
      messages.ValidationError if merged message is not initialized.
    """
    if not encoded_message.strip():
      return message_type()

    dictionary = json.loads(encoded_message)
    message = self.__decode_dictionary(message_type, dictionary)
    message.check_initialized()
    return message

  def __find_variant(self, value):
    """Find the messages.Variant type that describes this value.

    Args:
      value: The value whose variant type is being determined.

    Returns:
      The messages.Variant value that best describes value's type, or None if
      it's a type we don't know how to handle.
    """
    if isinstance(value, bool):
      return messages.Variant.BOOL
    elif isinstance(value, six.integer_types):
      return messages.Variant.INT64
    elif isinstance(value, float):
      return messages.Variant.DOUBLE
    elif isinstance(value, six.string_types):
      return messages.Variant.STRING
    elif isinstance(value, (list, tuple)):
      # Find the most specific variant that covers all elements.
      variant_priority = [None, messages.Variant.INT64, messages.Variant.DOUBLE,
                          messages.Variant.STRING]
      chosen_priority = 0
      for v in value:
        variant = self.__find_variant(v)
        try:
          priority = variant_priority.index(variant)
        except IndexError:
          priority = -1
        if priority > chosen_priority:
          chosen_priority = priority
      return variant_priority[chosen_priority]
    # Unrecognized type.
    return None

  def __decode_dictionary(self, message_type, dictionary):
    """Merge dictionary in to message.

    Args:
      message: Message to merge dictionary in to.
      dictionary: Dictionary to extract information from.  Dictionary
        is as parsed from JSON.  Nested objects will also be dictionaries.
    """
    message = message_type()
    for key, value in six.iteritems(dictionary):
      if value is None:
        try:
          message.reset(key)
        except AttributeError:
          pass  # This is an unrecognized field, skip it.
        continue

      try:
        field = message.field_by_name(key)
      except KeyError:
        # Save unknown values.
        variant = self.__find_variant(value)
        if variant:
          if key.isdigit():
            key = int(key)
          message.set_unrecognized_field(key, value, variant)
        else:
          logging.warning('No variant found for unrecognized field: %s', key)
        continue

      # Normalize values in to a list.
      if isinstance(value, list):
        if not value:
          continue
      else:
        value = [value]

      valid_value = []
      for item in value:
        valid_value.append(self.decode_field(field, item))

      if field.repeated:
        existing_value = getattr(message, field.name)
        setattr(message, field.name, valid_value)
      else:
        setattr(message, field.name, valid_value[-1])
    return message

  def decode_field(self, field, value):
    """Decode a JSON value to a python value.

    Args:
      field: A ProtoRPC field instance.
      value: A serialized JSON value.

    Return:
      A Python value compatible with field.
    """
    if isinstance(field, messages.EnumField):
      try:
        return field.type(value)
      except TypeError:
        raise messages.DecodeError('Invalid enum value "%s"' % (value or ''))

    elif isinstance(field, messages.BytesField):
      try:
        return base64.b64decode(value)
      except (binascii.Error, TypeError) as err:
        raise messages.DecodeError('Base64 decoding error: %s' % err)

    elif isinstance(field, message_types.DateTimeField):
      try:
        return util.decode_datetime(value)
      except ValueError as err:
        raise messages.DecodeError(err)

    elif (isinstance(field, messages.MessageField) and
          issubclass(field.type, messages.Message)):
      return self.__decode_dictionary(field.type, value)

    elif (isinstance(field, messages.FloatField) and
          isinstance(value, (six.integer_types, six.string_types))):
      try:
        return float(value)
      except:
        pass

    elif (isinstance(field, messages.IntegerField) and
          isinstance(value, six.string_types)):
      try:
        return int(value)
      except:
        pass

    return value

  @staticmethod
  def get_default():
    """Get default instanceof ProtoJson."""
    try:
      return ProtoJson.__default
    except AttributeError:
      ProtoJson.__default = ProtoJson()
      return ProtoJson.__default

  @staticmethod
  def set_default(protocol):
    """Set the default instance of ProtoJson.

    Args:
      protocol: A ProtoJson instance.
    """
    if not isinstance(protocol, ProtoJson):
      raise TypeError('Expected protocol of type ProtoJson')
    ProtoJson.__default = protocol

CONTENT_TYPE = ProtoJson.CONTENT_TYPE

ALTERNATIVE_CONTENT_TYPES = ProtoJson.ALTERNATIVE_CONTENT_TYPES

encode_message = ProtoJson.get_default().encode_message

decode_message = ProtoJson.get_default().decode_message
