package propagation.impl;

import propagation.Node;
import propagation.PropagationManager;
import propagation.PropagationRule;
import propagation.StateItem;

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

public class PropagationManagerImpl implements PropagationManager {
   private Node rootNode_;

   private Map nodeMap_ = new HashMap();

   private transient PropagationRule orRule_ = new ORSummaryRule();

   public void setRootNode(String rdn) {
      this.rootNode_ = createNode(rdn, rdn);
   }

   public Node createNode(String fdn, String rdn) {
      Node newNode = new NodeImpl();
      newNode.setNodeFDN(fdn);
      newNode.setNodeRDN(rdn);
      newNode.setPropagationRule(orRule_);

      StateItem summary = new StateItemImpl(0);
      summary.setState(PropagationRule.STATE_CLEAR);
      newNode.setSummaryStateItem(summary);

      registMap(newNode);

      return newNode;
   }

   public void setUpperNode(String upperFdn, String lowerFdn) {
      Node upperNode = findNode(upperFdn);
      Node lowerNode = findNode(lowerFdn);
      if ((upperNode != null) && (lowerNode != null)) {
         upperNode.addChildNode(lowerNode);
         lowerNode.addUpperNode(upperNode);
      }
   }

   public void addNode(String parentFdn, String rdn) {
      Node parent = findNode(parentFdn);
      if (parent != null) {
         Node node = createNode(parentFdn + "." + rdn, rdn);
         node.setParentNode(parent);
         parent.addChildNode(node);

         PropagationRule rule = node.getPropagationRule();
         rule.summaryUpperPropagate(node);
      }
   }

   public void addStateItem(String parentFdn, long itemId, String name, long defaultState) {
      Node node = findNode(parentFdn);
      if (node != null) {
         StateItem item = new StateItemImpl(itemId);
         item.setState(defaultState);
         item.setName(name);

         node.addStateItem(item);

         PropagationRule rule = node.getPropagationRule();
         rule.summaryUpperPropagate(node);
      }
   }

   public void stateChange(String fdn, long itemId, long newState) {
      Node node = findNode(fdn);
      if (node != null) {
         PropagationRule rule = node.getPropagationRule();
         rule.changeState(node, itemId, newState);
      }
   }

   public Node findNode(String fdn) {
      return (Node) nodeMap_.get(fdn);
   }

   public void printNodes() {
      printNode(rootNode_, "");
   }

   public void printNodes(String fdn) {
      Node node = findNode(fdn);
      if (node != null) {
         printNode(node, "");
      }
   }

   private void printNode(Node node, String prefix) {
      String str = "";
      if(node.getSummaryStateItem().getState() == 2000)
         str = " [ok]";

      System.out.println(prefix + node.getNodeRDN() + " (Summary : "
              + node.getSummaryStateItem().getState() +str + ")");

      String itemPrefix = prefix + " | ";
      List items = node.getStateItems();
      int size = items.size();
      for (int idx = 0; idx < size; idx++) {
         StateItem item = (StateItem) items.get(idx);
         printStateItem(item, itemPrefix);
      }

      String childPrefix = prefix + " + ";
      List children = node.getChildren();
      size = children.size();
      for (int idx = 0; idx < size; idx++) {
         Node child = (Node) children.get(idx);
         printNode(child, childPrefix);
      }
   }

   private void printStateItem(StateItem item, String prefix) {
      System.out.println(prefix + "( name = " + item.getName() + ", id = " +item.getItemId() + ", state ="
              + item.getState() + ")");
   }

   private void registMap(Node node) {
      this.nodeMap_.put(node.getNodeFDN(), node);
   }
}
