package com.eactive.eai.transformer.layout;

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

import com.eactive.eai.transformer.util.Logger;


public final class LayoutTreeBuilder {
	private static Logger logger = Logger.getLogger("transformer");
    private HashMap<Integer, Item> nodeMap;
    private List<Item> rootList;

    public LayoutTreeBuilder() {
        nodeMap = new HashMap<>();
        rootList = new ArrayList<>();
    }

    public void addNode(Item node) throws InvalidNodeException {
        // 등록
        nodeMap.put(node.getItemId(), node);
        // 상위 노드 가 없을 경우는 채움
        if (node.getParent() == null) {
            Item parent = nodeMap.get(node.getParentId());

            if (parent != null) {
                parent.addChild(node);
            } else {
                // 상위 노드가 결정되지 않으면 나주에 다시 시도
                // (ROOT인 가능성이 큼)
                addCandidateNode(node);
            }
        }
    }

    public int nodeSize() {
        return nodeMap.size();
    }

    private void addCandidateNode(Item node) {
        rootList.add(node);
    }

    private Item rebuildCandidateNode()
        throws TreeStructureException, InvalidNodeException {
        Item rootNode = null;

        int size = rootList.size();

        for (int i = 0; i < size; i++) {
            Item node = rootList.get(i);

            Item parent = nodeMap.get(new Integer(
                        node.getParentId()));

            if ((parent != null) && !(parent.equals(node))) {
                parent.addChild(node);
            } else {
                if (rootNode != null) {
                    // 현재 중복된 노드 출력
                    
                    if(logger.isWarnEnabled()){
                        logger.warn("========[ rebuildCandidateNode ]=========");
                        logger.warn("root node: " + rootNode.getParentId());
                        logger.warn("root node: " + rootNode.getName());
                        logger.warn("candidate: " + node.getParentId());
                        logger.warn("candidate: " + node.getName());
                        logger.warn("========[ rebuildCandidateNode ]=========");
                    }

                    throw new TreeStructureException("트리의 루트 노드가 중복되었습니다.",
                        rootNode);
                }
                rootNode = node;
            }
        }

        if (rootNode == null) {
            throw new TreeStructureException("트리의 루트 노드를 찾지 못했습니다.");
        }

        return rootNode;
    }

    public Item buildTree()
        throws TreeStructureException, InvalidNodeException {
        return rebuildCandidateNode();
    }
}
