"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
exports.GENERATION_TREE_ROOT_NAME = "__ROOT__";
exports.buildGenerationTree = function (_a) {
    var e_1, _b;
    var articles = _a.articles, _c = _a.include, include = _c === void 0 ? "all" : _c, apiUtil = _a.apiUtil;
    var elementList = new Map();
    /**
     * Recursively adds an element + children and neighbors to the tree
     *
     * @param {string} comId
     * @param {GenerationTreeMatchPointInfo} [snapPoint]
     * @returns
     */
    var addElement = function (comId, snapPoint) {
        var e_2, _a, e_3, _b;
        // element and children have already been added to the tree. we can skip scanning the subtree again
        if (elementList.has(comId)) {
            return;
        }
        var nodeData = {
            comId: comId,
            children: apiUtil.getDirectChildren(comId),
            snapPoint: snapPoint,
        };
        elementList.set(comId, nodeData);
        // skip snap point and neighbor detection for root element
        if (comId !== exports.GENERATION_TREE_ROOT_NAME) {
            if (snapPoint === undefined) {
                //TODO: use the exact match points and pass them to addElement instead of
                // calulculating the parent again
                nodeData.snapPoint = apiUtil.getDirectParent(comId);
            }
            if (include !== "children") {
                var neighborPoints = void 0;
                try {
                    neighborPoints = apiUtil.getNeighbors(comId);
                }
                catch (err) {
                    // no idea why this is erroring
                    console.error(err);
                }
                // add neighbors as children for this element
                if (neighborPoints !== undefined) {
                    try {
                        for (var neighborPoints_1 = tslib_1.__values(neighborPoints), neighborPoints_1_1 = neighborPoints_1.next(); !neighborPoints_1_1.done; neighborPoints_1_1 = neighborPoints_1.next()) {
                            var entry = neighborPoints_1_1.value;
                            if (elementList.has(entry.foreignComId)) {
                                continue;
                            }
                            nodeData.children.push(entry.foreignComId);
                            addElement(entry.foreignComId, {
                                foreignComId: comId,
                                ownPointKey: entry.foreignPointKey,
                                foreignPointKey: entry.ownPointKey,
                                type: entry.type,
                            });
                        }
                    }
                    catch (e_2_1) { e_2 = { error: e_2_1 }; }
                    finally {
                        try {
                            if (neighborPoints_1_1 && !neighborPoints_1_1.done && (_a = neighborPoints_1.return)) _a.call(neighborPoints_1);
                        }
                        finally { if (e_2) throw e_2.error; }
                    }
                }
            }
        }
        if (nodeData.children !== undefined) {
            try {
                for (var _c = tslib_1.__values(nodeData.children), _d = _c.next(); !_d.done; _d = _c.next()) {
                    var childComId = _d.value;
                    addElement(childComId);
                }
            }
            catch (e_3_1) { e_3 = { error: e_3_1 }; }
            finally {
                try {
                    if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
                }
                finally { if (e_3) throw e_3.error; }
            }
        }
    };
    elementList.set(exports.GENERATION_TREE_ROOT_NAME, {
        comId: exports.GENERATION_TREE_ROOT_NAME,
        children: articles,
    });
    var articlesWithPositions = articles.map(function (comId) { return (tslib_1.__assign({ comId: comId }, apiUtil.getScenePosition(comId))); });
    articlesWithPositions.sort(function (a, b) { return a.x + a.z - (b.x + b.z); });
    articlesWithPositions.forEach(function (element) { return addElement(element.comId); });
    var rootElement = elementList.get(exports.GENERATION_TREE_ROOT_NAME);
    var roots = new Set(rootElement.children);
    var findNonRoots = function (list) {
        var e_4, _a;
        try {
            for (var list_1 = tslib_1.__values(list), list_1_1 = list_1.next(); !list_1_1.done; list_1_1 = list_1.next()) {
                var comId = list_1_1.value;
                if (roots.has(comId)) {
                    roots.delete(comId);
                }
                var node = elementList.get(comId);
                if (node.children !== undefined) {
                    findNonRoots(node.children);
                }
            }
        }
        catch (e_4_1) { e_4 = { error: e_4_1 }; }
        finally {
            try {
                if (list_1_1 && !list_1_1.done && (_a = list_1.return)) _a.call(list_1);
            }
            finally { if (e_4) throw e_4.error; }
        }
    };
    try {
        // remove elements from root array, which are found somewhere else in the tree
        for (var roots_1 = tslib_1.__values(roots), roots_1_1 = roots_1.next(); !roots_1_1.done; roots_1_1 = roots_1.next()) {
            var comId = roots_1_1.value;
            var node = elementList.get(comId);
            if (node.children !== undefined) {
                findNonRoots(node.children);
            }
        }
    }
    catch (e_1_1) { e_1 = { error: e_1_1 }; }
    finally {
        try {
            if (roots_1_1 && !roots_1_1.done && (_b = roots_1.return)) _b.call(roots_1);
        }
        finally { if (e_1) throw e_1.error; }
    }
    rootElement.children = Array.from(roots);
    return elementList;
};
