"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ig_gfx_core_1 = require("@intelligentgraphics/ig.gfx.core");
var Operations_1 = require("./Operations");
var Util_1 = require("../Util");
/** Operation-strategy finder. */
var OperationStrategyFinder = /** @class */ (function () {
    function OperationStrategyFinder(converter) {
        this.converter = converter;
    }
    /** Gets a strategy based on the passed parameters.
     * @param parameters The parameters for chosing a strategy.
     * @returns The operation that comes closest to the parameters.
     */
    OperationStrategyFinder.prototype.getStrategy = function (parameters) {
        var movement = this.getMovementOperation(parameters);
        var snap = new Operations_1.SnapCheckOperation(movement, parameters.componentIds, this.converter, parameters.ignoredModes);
        if (parameters.ignoreCollisions) {
            return snap;
        }
        var collision = new Operations_1.CollisionCheckOperation(snap, parameters.componentIds);
        return new Operations_1.ValidResultOperation([collision]);
    };
    /**
     * Create the this.movementOperations field from the values specified in the parameters
     * If rotate is set, rotation will occur, otherwise a translation
     * Movement restriction is only applied if some restrictions are given and only a single object is selected
     * @param parameters
     */
    OperationStrategyFinder.prototype.getMovementOperation = function (parameters) {
        var operation;
        if (parameters.rotate) {
            operation = this.makeRotationOperation(parameters);
        }
        else {
            operation = this.makeTranslationOperation(parameters);
        }
        var doRestrictMovement = ig_gfx_core_1.areBoundsValid(parameters.bounds);
        if (doRestrictMovement) {
            return new Operations_1.ConstrainToBounds(operation, parameters.bounds, parameters.componentIds);
        }
        return operation;
    };
    /**
     * Create a Translation Operation, if necessary wrapped inside a Grid Operation
     * @param parameters
     * @returns {TranslationOperation | GridTranslationOperation}
     */
    OperationStrategyFinder.prototype.makeTranslationOperation = function (parameters) {
        var operation = new Operations_1.TranslationOperation(parameters.componentIds);
        if (parameters.movementGridLength > 0) {
            return new Operations_1.GridTranslationOperation(operation, parameters.movementGridLength);
        }
        return operation;
    };
    /**
     * Create a Rotation Operation, if necessary wrapped inside a Grid Operation
     * @param parameters
     * @returns
     */
    OperationStrategyFinder.prototype.makeRotationOperation = function (parameters) {
        var transformations = parameters.componentIds.map(function (x) {
            return ig_gfx_core_1.getWorldTransformation(x);
        });
        var positions = transformations.map(function (trafo) { return trafo.position; });
        var rotations = transformations.map(function (trafo) { return trafo.rotation; });
        var middlePoint = Util_1.calculateMiddlePointFromAllBoundingBoxes(parameters.componentIds);
        var operation = new Operations_1.RotationOperation(positions, rotations, middlePoint);
        if (parameters.rotationGridLength > 0 &&
            parameters.rotationGridLength < 2 * Math.PI) {
            return new Operations_1.GridRotationOperation(operation, parameters.rotationGridLength);
        }
        return operation;
    };
    return OperationStrategyFinder;
}());
exports.OperationStrategyFinder = OperationStrategyFinder;
