# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

"""
String formatting and string-based format utilities.
"""

import json
from types import MethodType

from ruamel import yaml  # @UnresolvedImport

from .collections import FrozenList, FrozenDict, StrictList, StrictDict, OrderedDict


PLURALIZE_EXCEPTIONS = {}


# Add our types to ruamel.yaml (for round trips)
yaml.representer.RoundTripRepresenter.add_representer(
    FrozenList, yaml.representer.RoundTripRepresenter.represent_list)
yaml.representer.RoundTripRepresenter.add_representer(
    FrozenDict, yaml.representer.RoundTripRepresenter.represent_dict)
yaml.representer.RoundTripRepresenter.add_representer(
    StrictList, yaml.representer.RoundTripRepresenter.represent_list)
yaml.representer.RoundTripRepresenter.add_representer(
    StrictDict, yaml.representer.RoundTripRepresenter.represent_dict)

# Without this, ruamel.yaml will output "!!omap" types, which is
# technically correct but unnecessarily verbose for our uses
yaml.representer.RoundTripRepresenter.add_representer(
    OrderedDict, yaml.representer.RoundTripRepresenter.represent_dict)


class JsonAsRawEncoder(json.JSONEncoder):
    """
    A :class:`JSONEncoder` that will use the ``as_raw`` property of objects if available.
    """
    def raw_encoder_default(self, obj):
        try:
            return iter(obj)
        except TypeError:
            if hasattr(obj, 'as_raw'):
                return as_raw(obj)
            return str(obj)
        return super(JsonAsRawEncoder, self).default(obj)

    def __init__(self, *args, **kwargs):
        kwargs['default'] = self.raw_encoder_default
        super(JsonAsRawEncoder, self).__init__(*args, **kwargs)


class YamlAsRawDumper(yaml.dumper.RoundTripDumper):  # pylint: disable=too-many-ancestors
    """
    A :class:`RoundTripDumper` that will use the ``as_raw`` property of objects if available.
    """

    def represent_data(self, data):
        if hasattr(data, 'as_raw'):
            data = as_raw(data)
        return super(YamlAsRawDumper, self).represent_data(data)


def decode_list(data):
    decoded_list = []
    for item in data:
        if isinstance(item, unicode):
            item = item.encode('utf-8')
        elif isinstance(item, list):
            item = decode_list(item)
        elif isinstance(item, dict):
            item = decode_dict(item)
        decoded_list.append(item)
    return decoded_list


def decode_dict(data):
    decoded_dict = {}
    for key, value in data.iteritems():
        if isinstance(key, unicode):
            key = key.encode('utf-8')
        if isinstance(value, unicode):
            value = value.encode('utf-8')
        elif isinstance(value, list):
            value = decode_list(value)
        elif isinstance(value, dict):
            value = decode_dict(value)
        decoded_dict[key] = value
    return decoded_dict


def safe_str(value):
    """
    Like :class:`str` coercion, but makes sure that Unicode strings are properly encoded, and will
    never return ``None``.
    """

    try:
        return str(value)
    except UnicodeEncodeError:
        return unicode(value).encode('utf8')


def safe_repr(value):
    """
    Like :func:`repr`, but calls :func:`as_raw` and :func:`as_agnostic` first.
    """

    return repr(as_agnostic(as_raw(value)))


def string_list_as_string(strings):
    """
    Nice representation of a list of strings.
    """

    if not strings:
        return 'none'
    return ', '.join('"{0}"'.format(safe_str(v)) for v in strings)


def pluralize(noun):
    plural = PLURALIZE_EXCEPTIONS.get(noun)
    if plural is not None:
        return plural
    elif noun.endswith('s'):
        return '{0}es'.format(noun)
    elif noun.endswith('y'):
        return '{0}ies'.format(noun[:-1])
    else:
        return '{0}s'.format(noun)


def as_raw(value):
    """
    Converts values using their ``as_raw`` property, if it exists, recursively.
    """

    if hasattr(value, 'as_raw'):
        value = value.as_raw
        if isinstance(value, MethodType):
            # Old-style Python classes don't support properties
            value = value()
    elif isinstance(value, list):
        value = list(value)
        for i, v in enumerate(value):
            value[i] = as_raw(v)
    elif isinstance(value, dict):
        value = dict(value)
        for k, v in value.iteritems():
            value[k] = as_raw(v)
    return value


def as_raw_list(value):
    """
    Assuming value is a list, converts its values using :func:`as_raw`.
    """

    if value is None:
        return []
    if isinstance(value, dict):
        value = value.itervalues()
    return [as_raw(v) for v in value]


def as_raw_dict(value):
    """
    Assuming value is a dict, converts its values using :func:`as_raw`. The keys are left as is.
    """

    if value is None:
        return OrderedDict()
    return OrderedDict((
        (k, as_raw(v)) for k, v in value.iteritems()))


def as_agnostic(value):
    """
    Converts subclasses of list and dict to standard lists and dicts, and Unicode strings to
    non-Unicode if possible, recursively.

    Useful for creating human-readable output of structures.
    """

    if isinstance(value, unicode):
        try:
            value = str(value)
        except UnicodeEncodeError:
            pass
    elif isinstance(value, list):
        value = list(value)
    elif isinstance(value, dict):
        value = dict(value)

    if isinstance(value, list):
        for i, _ in enumerate(value):
            value[i] = as_agnostic(value[i])
    elif isinstance(value, dict):
        for k, v in value.iteritems():
            value[k] = as_agnostic(v)

    return value


def json_dumps(value, indent=2):
    """
    JSON dumps that supports Unicode and the ``as_raw`` property of objects if available.
    """

    return json.dumps(value, indent=indent, ensure_ascii=False, cls=JsonAsRawEncoder)


def yaml_dumps(value, indent=2):
    """
    YAML dumps that supports Unicode and the ``as_raw`` property of objects if available.
    """

    return yaml.dump(value, indent=indent, allow_unicode=True, Dumper=YamlAsRawDumper)


def yaml_loads(value):
    return yaml.load(value, Loader=yaml.SafeLoader)
