# 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 .yaml 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)
