# Contributors Listed Below - COPYRIGHT 2016
# [+] International Business Machines Corp.
#
#
# 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.


class PathTreeItemIterator(object):
    def __init__(self, path_tree, subtree, depth):
        self.path_tree = path_tree
        self.path = []
        self.itlist = []
        self.subtree = ['/'] + list(filter(bool, subtree.split('/')))
        self.depth = depth
        d = path_tree.root
        for k in self.subtree:
            try:
                d = d[k]['children']
            except KeyError:
                raise KeyError(subtree)
        # TODO: openbmc/openbmc#2994 remove python 2 support
        try:  # python 2
            self.it = d.iteritems()
        except AttributeError:  # python 3
            self.it = iter(d.items())

    def __iter__(self):
        return self

    # TODO: openbmc/openbmc#2994 remove python 2 support
    # python 2
    def next(self):
        key, value = self._next()
        path = self.subtree[0] + '/'.join(self.subtree[1:] + self.path)
        return path, value.get('data')

    # python 3
    import sys
    if sys.version_info[0] > 2:
        __next__ = next

    def _next(self):
        try:
            while True:
                x = next(self.it)
                if self.depth:
                    if len(self.path) + 1 > self.depth:
                        continue
                self.itlist.append(self.it)
                self.path.append(x[0])
                # TODO: openbmc/openbmc#2994 remove python 2 support
                try:  # python 2
                    self.it = x[1]['children'].iteritems()
                except AttributeError:  # python 3
                    self.it = iter(x[1]['children'].items())
                break

        except StopIteration:
            if not self.itlist:
                raise StopIteration

            self.it = self.itlist.pop()
            self.path.pop()
            x = self._next()

        return x


class PathTreeKeyIterator(PathTreeItemIterator):
    def __init__(self, path_tree, subtree, depth):
        super(PathTreeKeyIterator, self).__init__(path_tree, subtree, depth)

    # TODO: openbmc/openbmc#2994 remove python 2 support
    # python 2
    def next(self):
        return super(PathTreeKeyIterator, self).next()[0]

    # python 3
    import sys
    if sys.version_info[0] > 2:
        __next__ = next


class PathTree:
    def __init__(self):
        self.root = {}

    def _try_delete_parent(self, elements):
        if len(elements) == 1:
            return False

        kids = 'children'
        elements.pop()
        d = self.root
        for k in elements[:-1]:
            d = d[k][kids]

        if 'data' not in d[elements[-1]] and not d[elements[-1]][kids]:
            del d[elements[-1]]
            self._try_delete_parent(elements)

    def _get_node(self, key):
        kids = 'children'
        elements = ['/'] + list(filter(bool, key.split('/')))
        d = self.root
        for k in elements[:-1]:
            try:
                d = d[k][kids]
            except KeyError:
                raise KeyError(key)

        return d[elements[-1]]

    def __iter__(self):
        return PathTreeItemIterator(self, '/', None)

    def __missing__(self, key):
        for x in self.iterkeys():
            if key == x:
                return False
        return True

    def __delitem__(self, key):
        kids = 'children'
        elements = ['/'] + list(filter(bool, key.split('/')))
        d = self.root
        for k in elements[:-1]:
            try:
                d = d[k][kids]
            except KeyError:
                raise KeyError(key)

        del d[elements[-1]]
        self._try_delete_parent(elements)

    def __setitem__(self, key, value):
        kids = 'children'
        elements = ['/'] + list(filter(bool, key.split('/')))
        d = self.root
        for k in elements[:-1]:
            d = d.setdefault(k, {kids: {}})[kids]

        children = d.setdefault(elements[-1], {kids: {}})[kids]
        d[elements[-1]].update({kids: children, 'data': value})

    def __getitem__(self, key):
        return self._get_node(key).get('data')

    def setdefault(self, key, default):
        if not self.get(key):
            self.__setitem__(key, default)

        return self.__getitem__(key)

    def get(self, key, default=None):
        try:
            x = self.__getitem__(key)
        except KeyError:
            x = default

        return x

    def get_children(self, key):
        return [x for x in self._get_node(key)['children'].keys()]

    def demote(self, key):
        n = self._get_node(key)
        if 'data' in n:
            del n['data']

    def keys(self, subtree='/', depth=None):
        return [x for x in self.iterkeys(subtree, depth)]

    def values(self, subtree='/', depth=None):
        return [x[1] for x in self.iteritems(subtree, depth)]

    def items(self, subtree='/', depth=None):
        return [x for x in self.iteritems(subtree, depth)]

    def dataitems(self, subtree='/', depth=None):
        return [x for x in self.iteritems(subtree, depth)
                if x[1] is not None]

    def iterkeys(self, subtree='/', depth=None):
        if not self.root:
            # TODO: openbmc/openbmc#2994 remove python 2 support
            try:  # python 2
                return {}.iterkeys()
            except AttributeError:  # python 3
                return iter({}.keys())
        return PathTreeKeyIterator(self, subtree, depth)

    def iteritems(self, subtree='/', depth=None):
        if not self.root:
            # TODO: openbmc/openbmc#2994 remove python 2 support
            try:  # python 2
                return {}.iteritems()
            except AttributeError:  # python 3
                return iter({}.items())
        return PathTreeItemIterator(self, subtree, depth)

    def dumpd(self, subtree='/'):
        result = {}
        d = result

        for k, v in self.iteritems(subtree):
            elements = ['/'] + list(filter(bool, k.split('/')))
            d = result
            for k in elements:
                d = d.setdefault(k, {})
            if v is not None:
                d.update(v)

        return result
