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

from copy import deepcopy


from ...utils.console import puts, Colored, indent


# We are inheriting the primitive types in order to add the ability to set
# an attribute (_locator) on them.

class LocatableString(unicode):
    pass


class LocatableInt(int):
    pass


class LocatableFloat(float):
    pass


def wrap(value):
    if isinstance(value, basestring):
        return True, LocatableString(value)
    elif isinstance(value, int) and \
            not isinstance(value, bool):  # Note: bool counts as int in Python!
        return True, LocatableInt(value)
    elif isinstance(value, float):
        return True, LocatableFloat(value)
    return False, value


class Locator(object):
    """
    Stores location information (line and column numbers) for agnostic raw data.
    """
    def __init__(self, location, line, column, children=None):
        self.location = location
        self.line = line
        self.column = column
        self.children = children

    def get_child(self, *names):
        if (not names) or (not isinstance(self.children, dict)):
            return self
        name = names[0]
        if name not in self.children:
            return self
        child = self.children[name]
        return child.get_child(names[1:])

    def link(self, raw, path=None):
        if hasattr(raw, '_locator'):
            # This can happen when we use anchors
            return

        try:
            setattr(raw, '_locator', self)
        except AttributeError:
            return

        if isinstance(raw, list):
            for i, raw_element in enumerate(raw):
                wrapped, raw_element = wrap(raw_element)
                if wrapped:
                    raw[i] = raw_element
                child_path = '%s.%d' % (path, i) if path else str(i)
                try:
                    self.children[i].link(raw_element, child_path)
                except KeyError:
                    raise ValueError('location map does not match agnostic raw data: %s' %
                                     child_path)
        elif isinstance(raw, dict):
            for k, raw_element in raw.iteritems():
                wrapped, raw_element = wrap(raw_element)
                if wrapped:
                    raw[k] = raw_element
                child_path = '%s.%s' % (path, k) if path else k
                try:
                    self.children[k].link(raw_element, child_path)
                except KeyError:
                    raise ValueError('location map does not match agnostic raw data: %s' %
                                     child_path)

    def merge(self, locator):
        if isinstance(self.children, dict) and isinstance(locator.children, dict):
            for k, loc in locator.children.iteritems():
                if k in self.children:
                    self.children[k].merge(loc)
                else:
                    self.children[k] = loc

    def dump(self, key=None):
        if key:
            puts('%s "%s":%d:%d' %
                 (Colored.red(key), Colored.blue(self.location), self.line, self.column))
        else:
            puts('"%s":%d:%d' % (Colored.blue(self.location), self.line, self.column))
        if isinstance(self.children, list):
            with indent(2):
                for loc in self.children:
                    loc.dump()
        elif isinstance(self.children, dict):
            with indent(2):
                for k, loc in self.children.iteritems():
                    loc.dump(k)

    def __str__(self):
        # Should be in same format as Issue.locator_as_str
        return '"%s":%d:%d' % (self.location, self.line, self.column)


def deepcopy_with_locators(value):
    """
    Like :code:`deepcopy`, but also copies over locators.
    """

    res = deepcopy(value)
    copy_locators(res, value)
    return res


def copy_locators(target, source):
    """
    Copies over :code:`_locator` for all elements, recursively.

    Assumes that target and source have exactly the same list/dict structure.
    """

    locator = getattr(source, '_locator', None)
    if locator is not None:
        try:
            setattr(target, '_locator', locator)
        except AttributeError:
            pass

    if isinstance(target, list) and isinstance(source, list):
        for i, _ in enumerate(target):
            copy_locators(target[i], source[i])
    elif isinstance(target, dict) and isinstance(source, dict):
        for k, v in target.items():
            copy_locators(v, source[k])
