import { __read, __spread } from "tslib";
import _ from "lodash";
import * as Core from "@intelligentgraphics/ig.gfx.core";
import * as Associates from "./Associates";
import { StrongNeighborMatch } from "./Interactor/SnapMatches";
import SnapPoints from "./Interactor/SnapPoints";
import { cartesianProduct } from "./Util";
/**
 * Class for connecting articles (e.g. after a change in dimension or a movement)
 * Has to be initiated before the disconnection starts.
 */
var ArticleConnector = /** @class */ (function () {
    function ArticleConnector(left, right) {
        this.left = left;
        this.right = right;
    }
    /**
     * Restore the connection.
     * Only works if there are matching attachpoints in the neighbor group of the left and right element.
     */
    ArticleConnector.prototype.connect = function () {
        var neighbors = __spread(Associates.getNeighbors([this.right], true), [
            this.right,
        ]);
        var gfxIdsToMove = __spread(neighbors, Associates.getChildren(neighbors, true));
        // component are already neighbors
        if (_.includes(gfxIdsToMove, this.left)) {
            return;
        }
        var match = this.closestMatch();
        if (!match) {
            return;
        }
        gfxIdsToMove.forEach(function (id) {
            var componentTrafo = Core.getWorldTransformation(id);
            var adaptedTrafo = match.adaptTransformation(componentTrafo);
            Core.State.API.SetTransformation(id, adaptedTrafo);
        });
    };
    /**
     * Get the closest match to use for the connection.
     * We need to consider the "Left" points of the right group and the "Right" points of the left group.
     * @returns {any}
     */
    ArticleConnector.prototype.closestMatch = function () {
        var pointsOnTheRight = new SnapPoints({ id: this.right }, true).strongNeighborSnapPoints.filter(function (pt) { return pt.type === "Left"; });
        var pointsOnTheLeft = new SnapPoints({ id: this.left }, true).strongNeighborSnapPoints.filter(function (pt) { return pt.type === "Right"; });
        return this.bestMatch(pointsOnTheRight, pointsOnTheLeft, this.left, this.right);
    };
    /**
     * Make all possible matches and sort by distance so that the first match is the one with the closest distance
     * @param firstPoints
     * @param secondPoints
     * @param first
     * @param second
     * @returns {any}
     */
    ArticleConnector.prototype.bestMatch = function (firstPoints, secondPoints, first, second) {
        var matches = cartesianProduct(firstPoints, secondPoints).map(function (_a) {
            var _b = __read(_a, 2), firstPoint = _b[0], secondPoint = _b[1];
            return new StrongNeighborMatch(firstPoint, secondPoint, first, second);
        });
        return _.first(_.orderBy(matches, function (m) { return m.distance; }, "asc"));
    };
    return ArticleConnector;
}());
export { ArticleConnector };
