"""
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:
-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'

    This file is part of JMOO,
    Copyright Joe Krall, 2014.

    JMOO is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    JMOO is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with JMOO.  If not, see <http://www.gnu.org/licenses/>.

-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:
-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'

"""


class Requirement(object):
    def __init__(self, c, v):
        #cost of the task
        self.cost = c

        #value of the task (priority)
        self.value = v

        #if the task is done or not
        self.done = False

        #if the task is visible (invisible tasks technically have not been planned at all by project leaders)
        self.visible = False

    def __repr__(self):
        return "Done? " + str(self.done) + ".  (Cost: " + str(
            self.cost) + ", Value: " + str(self.value) + ")"


class requirements_node(object):
    def __init__(self, v, k, p=None, c=[], l=0):
        self.val = v
        self.key = k
        self.parent = p
        self.children = c
        self.level = l
        self.dependencies = []

    def add_child(self, v, k, l):
        self.children.append(requirements_node(v, k, self, [], l))

    def __repr__(self):
        if self.parent:
            return (" " * self.level + "{Key: " + self.key + ", Val: " + str(
                self.val) + ", ParentKey = " + self.parent.key + " Dep: " +
                    str(self.dependencies) + "}")
        else:
            return (" " * self.level + "{Key: " + self.key + ", Val: " + str(
                self.val) + ", ParentKey = None" + " Dep: " + str(
                    self.dependencies) + "}")

    def show(self):
        print(self)
        for child in self.children:
            child.show()

    def iterative_search(self, k):
        for child in self.children:
            if child.key == k: return child
            else:
                result = child.iterative_search(k)
                if result: return result

    def max_depth(self):
        max = 0
        for child in self.children:
            if child.level > max: max = child.level
            m = child.max_depth()
            if m > max: max = m
        return max

    def traverse(self):
        list = []
        for child in self.children:
            list.append(child)
            to_add = child.traverse()
            for i in to_add:
                list.append(i)
        return list


class requirements_tree(object):
    def __init__(self):
        self.tree = []

    def add_root(self, v, k):
        self.tree.append(requirements_node(v, k, None, [], 0))

    def get_root(self, k):
        for root in self.tree:
            if root.key == k: return root

    def find_node(self, k):
        for root in self.tree:
            if root.key == k: return root
            else:
                result = root.iterative_search(k)
                if result: return result

    def get_level(self, root, level):
        list = []
        if (root.level < level):
            for child in root.children:
                list.append(self.get_level(child, level))
        elif (root.level == level):
            list.append(root.key)
        return list

    def traverse(self):
        list = []
        for root in self.tree:
            list.append(root)
            to_add = root.traverse()
            for i in to_add:
                list.append(i)
        return list

    def show(self):
        for root in self.tree:
            root.show()