import { getWorldTransformation, areBoundsValid, } from "@intelligentgraphics/ig.gfx.core";
import { SnapCheckOperation, RotationOperation, TranslationOperation, GridTranslationOperation, GridRotationOperation, ConstrainToBounds, CollisionCheckOperation, ValidResultOperation, } from "./Operations";
import { calculateMiddlePointFromAllBoundingBoxes } from "../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 SnapCheckOperation(movement, parameters.componentIds, this.converter, parameters.ignoredModes);
        if (parameters.ignoreCollisions) {
            return snap;
        }
        var collision = new CollisionCheckOperation(snap, parameters.componentIds);
        return new 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 = areBoundsValid(parameters.bounds);
        if (doRestrictMovement) {
            return new 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 TranslationOperation(parameters.componentIds);
        if (parameters.movementGridLength > 0) {
            return new 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 getWorldTransformation(x);
        });
        var positions = transformations.map(function (trafo) { return trafo.position; });
        var rotations = transformations.map(function (trafo) { return trafo.rotation; });
        var middlePoint = calculateMiddlePointFromAllBoundingBoxes(parameters.componentIds);
        var operation = new RotationOperation(positions, rotations, middlePoint);
        if (parameters.rotationGridLength > 0 &&
            parameters.rotationGridLength < 2 * Math.PI) {
            return new GridRotationOperation(operation, parameters.rotationGridLength);
        }
        return operation;
    };
    return OperationStrategyFinder;
}());
export { OperationStrategyFinder };
