/*
 * This file is part of NavalPlan
 *
 * Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
 *                    Desenvolvemento Tecnolóxico de Galicia
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.navalplanner.web.scenarios;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.navalplanner.business.scenarios.entities.Scenario;
import org.zkoss.zul.SimpleTreeModel;
import org.zkoss.zul.SimpleTreeNode;

/**
 * Model for the {@link Scenario} tree.
 *
 * @author Manuel Rego Casasnovas <mrego@igalia.com>
 */
public class ScenariosTreeModel extends SimpleTreeModel {

    private static Map<Scenario, List<Scenario>> relationParentChildren = new HashMap<Scenario, List<Scenario>>();

    public ScenariosTreeModel(ScenarioTreeRoot root) {
        super(createRootNodeAndDescendants(root, root.getRootScenarios(), root
                .getDerivedScenarios()));
    }

    private static SimpleTreeNode createRootNodeAndDescendants(
            ScenarioTreeRoot root, List<Scenario> rootScenarios,
            List<Scenario> derivedScenarios) {

        fillHashParentChildren(rootScenarios, derivedScenarios);

        return new SimpleTreeNode(root, asNodes(rootScenarios));
    }

    private static List<SimpleTreeNode> asNodes(List<Scenario> scenarios) {
        if (scenarios == null) {
            return new ArrayList<SimpleTreeNode>();
        }

        ArrayList<SimpleTreeNode> result = new ArrayList<SimpleTreeNode>();
        for (Scenario scenario : scenarios) {
            result.add(asNode(scenario));
        }

        return result;
    }

    private static SimpleTreeNode asNode(Scenario scenario) {
        List<Scenario> children = relationParentChildren.get(scenario);
        return new SimpleTreeNode(scenario, asNodes(children));
    }

    private static void fillHashParentChildren(
            List<Scenario> rootScenarios,
            List<Scenario> derivedScenarios) {
        for (Scenario root : rootScenarios) {
            relationParentChildren.put(root, new ArrayList<Scenario>());
        }

        for (Scenario derived : derivedScenarios) {
            Scenario parent = derived.getPredecessor();
            List<Scenario> siblings = relationParentChildren.get(parent);

            if (siblings == null) {
                siblings = new ArrayList<Scenario>();
                siblings.add(derived);
                relationParentChildren.put(parent, siblings);
            } else {
                siblings.add(derived);
            }
        }
    }

    @Override
    public boolean isLeaf(Object node) {
        if (node == null) {
            return true;
        }

        SimpleTreeNode simpleTreeNode = (SimpleTreeNode) node;
        Scenario scenario = (Scenario) simpleTreeNode.getData();

        List<Scenario> children = relationParentChildren.get(scenario);
        if (children == null) {
            return true;
        }

        return children.isEmpty();
    }

}

@@ -1287,124 +1287,8 @@
  %7B%0A%0A
-    private static Map%3CScenario, List%3CScenario%3E%3E relationParentChildren = new HashMap%3CScenario, List%3CScenario%3E%3E();%0A%0A
     
@@ -1642,25 +1642,24 @@
 rios) %7B%0A
-%0A
         
 fillHash
@@ -1650,16 +1650,56 @@
         
+return new SimpleTreeNode(root, asNodes(
 fillHash
@@ -1713,16 +1713,33 @@
 hildren(
+%0A                
 rootScen
@@ -1766,59 +1766,10 @@
 ios)
-;%0A%0A        return new SimpleTreeNode(root, asNodes(
+, 
 root
@@ -1836,16 +1836,84 @@
 asNodes(
+%0A            Map%3CScenario, List%3CScenario%3E%3E childrenMap,%0A            
 List%3CSce
@@ -2176,24 +2176,37 @@
 .add(asNode(
+childrenMap, 
 scenario));%0A
@@ -2287,16 +2287,72 @@
  asNode(
+%0A            Map%3CScenario, List%3CScenario%3E%3E childrenMap, 
 Scenario
@@ -2398,38 +2398,27 @@
 ldren = 
-relationParentC
+c
 hildren
+Map
 .get(sce
@@ -2477,16 +2477,29 @@
 asNodes(
+childrenMap, 
 children
@@ -2532,12 +2532,37 @@
 tic 
-void
+Map%3CScenario, List%3CScenario%3E%3E
  fil
@@ -2663,32 +2663,120 @@
 vedScenarios) %7B%0A
+        Map%3CScenario, List%3CScenario%3E%3E result = new HashMap%3CScenario, List%3CScenario%3E%3E();%0A
         for (Sce
@@ -2819,36 +2819,20 @@
       re
-lationParentChildren
+sult
 .put(roo
@@ -3021,36 +3021,20 @@
 ngs = re
-lationParentChildren
+sult
 .get(par
@@ -3187,36 +3187,20 @@
       re
-lationParentChildren
+sult
 .put(par
@@ -3307,432 +3307,25 @@
     
-%7D%0A%0A    @Override%0A    public boolean isLeaf(Object node) %7B%0A        if (node == null) %7B%0A            return true;%0A        %7D%0A%0A        SimpleTreeNode simpleTreeNode = (SimpleTreeNode) node;%0A        Scenario scenario = (Scenario) simpleTreeNode.getData();%0A%0A        List%3CScenario%3E children = relationParentChildren.get(scenario);%0A        if (children == null) %7B%0A            return true;%0A        %7D%0A%0A        return children.isEmpty()
+    return result
 ;%0A  

Fix bug. Scenarios don't appear repeated.