"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ig_gfx_core_1 = require("@intelligentgraphics/ig.gfx.core");
var ig_utilities_1 = require("@intelligentgraphics/ig.utilities");
var AssociatesCache = /** @class */ (function () {
    function AssociatesCache(api) {
        this.api = api;
        this.convertedPoints = {};
        // caching Associations and "Non-Associations" and unknown respectively
        /**
         * parent connection aka getParent()
         *
         * @private
         * @type {TypeSpecificAssociationCache}
         */
        this.gfx2parent = {};
        /**
         * children aka getChildren()
         *
         * @private
         * @type {TypeSpecificAssociationCache}
         */
        this.gfx2children = {};
        /**
         *  neighbors aka getNeighbor()
         *
         * @private
         * @type {TypeSpecificAssociationCache}
         */
        this.gfx2neighbors = {};
    }
    AssociatesCache.prototype.invalidateRoot = function (rootId) {
        if (!ig_gfx_core_1.Hierarchy.isRootGfxId(rootId)) {
            return;
        }
        this.convertedPoints[rootId] = undefined;
        this.invalidateCertainAssociation(rootId, this.gfx2parent);
        this.invalidateCertainAssociation(rootId, this.gfx2children);
        this.invalidateCertainAssociation(rootId, this.gfx2neighbors);
    };
    AssociatesCache.prototype.getConvertedPoints = function (gfxId, wantedType) {
        var _this = this;
        if (!gfxId || !wantedType) {
            return [];
        }
        var tResult = [];
        if (this.convertedPoints[gfxId] &&
            this.convertedPoints[gfxId][wantedType] != undefined) {
            tResult = this.convertedPoints[gfxId][wantedType];
            //console.log("gcp cached ", gfxid, wantedtype);
        }
        else {
            // fill all points for this gfxentry
            if (!this.convertedPoints[gfxId]) {
                this.convertedPoints[gfxId] = {};
            }
            var componentPosition_1 = ig_gfx_core_1.State.API.GetPosition(gfxId);
            var componentYRotation_1 = ig_gfx_core_1.State.API.GetYRotation(gfxId) * ig_gfx_core_1.Deg2Rad;
            var pointsOfChild = ig_gfx_core_1.State.API.GetPoints(gfxId);
            pointsOfChild.forEach(function (point) {
                point.ConvertForObject(componentPosition_1, componentYRotation_1);
                var ttype = point.type;
                if (!_this.convertedPoints[gfxId][ttype]) {
                    _this.convertedPoints[gfxId][ttype] = [];
                }
                _this.convertedPoints[gfxId][ttype].push(point);
            });
            tResult = this.convertedPoints[gfxId][wantedType] || [];
            // cache also empty cases
            if (tResult.length === 0) {
                this.convertedPoints[gfxId][wantedType] = [];
            }
            //console.log("gcp new", gfxid, wantedtype, tResult);
        }
        return tResult;
    };
    /**
     * set explicit Association
     *
     * @param {string} componentId
     * @param {string} foundParentId
     * @param {Association} association
     */
    AssociatesCache.prototype.setParent = function (componentId, foundParentId, association) {
        this.gfx2parent[componentId] = {};
        this.gfx2parent[componentId][foundParentId] = association;
    };
    AssociatesCache.prototype.setNonParents = function (componentId, notParents) {
        this.setMultiNotAssociations(this.gfx2parent, componentId, notParents);
    };
    /**
     * Returns 1 parent association
     * or explicit "has no parent" i.e. null
     * or list of gfxids that have to be checked
     *
     * @param componentId
     */
    AssociatesCache.prototype.getParent = function (componentId) {
        var temp = this.getMultiAssociations(this.gfx2parent, componentId);
        if (temp.knowns.length > 0) {
            return temp.knowns[0];
        }
        if (temp.unknowns.length < 1) {
            return null;
        }
        return temp.unknowns;
    };
    AssociatesCache.prototype.setChildren = function (componentId, associations) {
        this.setMultiAssociation(this.gfx2children, componentId, associations);
    };
    AssociatesCache.prototype.setNonChildren = function (componentId, notChildren) {
        this.setMultiNotAssociations(this.gfx2children, componentId, notChildren);
    };
    AssociatesCache.prototype.getChildren = function (componentId) {
        return this.getMultiAssociations(this.gfx2children, componentId);
    };
    AssociatesCache.prototype.setNeighbors = function (componentId, associations) {
        this.setMultiAssociation(this.gfx2neighbors, componentId, associations);
    };
    AssociatesCache.prototype.setNonNeighbors = function (componentId, notNeighbors) {
        this.setMultiNotAssociations(this.gfx2neighbors, componentId, notNeighbors);
    };
    AssociatesCache.prototype.getNeighbors = function (componentId) {
        return this.getMultiAssociations(this.gfx2neighbors, componentId);
    };
    /**
     * after moving a gfxid, its respective associations are set from YES or NO to UNKNOWN
     *
     * @private
     * @param {string} gfxId
     * @param {(TypeSpecificAssociationCache | undefined)} typeCache
     * @returns
     */
    AssociatesCache.prototype.invalidateCertainAssociation = function (gfxId, typeCache) {
        if (!typeCache) {
            return;
        }
        // invalidate myself, i.e. a "line"
        typeCache[gfxId] = undefined;
        // invalidate parts of others, i.e. a "column"
        Object.keys(typeCache).forEach(function (cachekey) {
            if (typeCache[cachekey]) {
                typeCache[cachekey][gfxId] = undefined;
            }
        });
    };
    /**
     * Enter a bunch of Associations for the given component
     * into the given cache
     *
     * @private
     * @param {TypeSpecificAssociationCache} multicache
     * @param {string} componentId
     * @param {Association[]} associations
     */
    AssociatesCache.prototype.setMultiAssociation = function (multicache, componentId, associations) {
        if (!multicache[componentId]) {
            multicache[componentId] = {};
        }
        associations.forEach(function (e) {
            multicache[componentId][e.otherId] = e;
        });
    };
    /**
     * Enter a bunch of explicit "NOT-Associations" into given cache
     *
     * @param multiCache
     * @param componentId
     * @param notparents
     */
    AssociatesCache.prototype.setMultiNotAssociations = function (multiCache, componentId, nots) {
        if (!componentId || !nots) {
            return;
        }
        if (!multiCache[componentId]) {
            multiCache[componentId] = {};
        }
        nots.forEach(function (np) {
            multiCache[componentId][np] = null; // explicit not a parent
        });
    };
    /**
     * actually read the known associations and the gfxs whose state is unknown
     *
     * @private
     * @param {TypeSpecificAssociationCache} multicache
     * @param {string} componentId
     * @returns {{ knowns: Association[]; unknowns: string[] }}
     */
    AssociatesCache.prototype.getMultiAssociations = function (multicache, componentId) {
        var _this = this;
        var otherRoots = this.api
            .GetRoots()
            .filter(function (rootId) {
            return rootId !== componentId &&
                ig_utilities_1.isValue(_this.api.GetComponent(rootId));
        });
        if (!multicache) {
            return { knowns: [], unknowns: otherRoots };
        }
        var line = multicache[componentId];
        if (!line) {
            return { knowns: [], unknowns: otherRoots };
        }
        // find out already known children, already known nonchildren and unknowns
        var founds = [];
        var toLookAts = [];
        otherRoots.forEach(function (r) {
            if (line[r] === undefined) {
                toLookAts.push(r);
            }
            if (line[r] !== null && line[r] !== undefined) {
                founds.push(line[r]);
            }
        });
        return {
            knowns: founds,
            unknowns: toLookAts,
        };
    };
    return AssociatesCache;
}());
exports.AssociatesCache = AssociatesCache;
