package ru.yandex.wmconsole.service;

import ru.yandex.wmconsole.data.Node;
import ru.yandex.wmconsole.data.info.TreeNodeInfo;
import ru.yandex.wmtools.common.error.InternalException;
import ru.yandex.wmtools.common.error.InternalProblem;
import ru.yandex.wmtools.common.service.AbstractDbService;

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

/**
 * User: baton
 * Date: 20.03.2007
 * Time: 10:09:24
 */
public abstract class TreeService extends AbstractDbService {
    private HostInfoService hostInfoService;

    public HostInfoService getHostInfoService() {
        return hostInfoService;
    }

    public void setHostInfoService(HostInfoService hostInfoService) {
        this.hostInfoService = hostInfoService;
    }

    protected Node convertListToTree(List<TreeNodeInfo> list, Map<Long, Node> id2node) throws InternalException {
        Node rootNode = null;
        Map<Long, List<Node>> id2children = new HashMap<Long, List<Node>>();
        for (TreeNodeInfo info: list) {
            Long parentId = info.getParentId();
            Node node = new Node(createTreeNodeInfo(info));

            List<Node> childrenList = id2children.get(info.getId());
            if (childrenList != null) {
                node.getChildren().addAll(childrenList);
                node.getInfo().setHasChildren(true);
                id2children.remove(info.getId());
            }

            if (info.getParentId() != null) {
                Node parentNode = id2node.get(parentId);
                if (parentNode == null) {
                    List<Node> parentChildrenList = id2children.get(parentId);
                    if (parentChildrenList == null) {
                        parentChildrenList = new ArrayList<Node>();
                        id2children.put(parentId, parentChildrenList);
                    }
                    parentChildrenList.add(node);
                } else {
                    parentNode.getChildren().add(node);
                    parentNode.getInfo().setHasChildren(true);
                }
            } else {
                rootNode = node;
            }
            id2node.put(info.getId(), node);
        }

        if (rootNode == null) {
            throw new InternalException(InternalProblem.READ_DB_ERROR, "No root node found in tree.");
        }
        return rootNode;
    }

    protected abstract TreeNodeInfo createTreeNodeInfo(TreeNodeInfo info);
}
