import * as Core from "@intelligentgraphics/ig.gfx.core";
/** An operation that rotates around a point. */
var RotationOperation = /** @class */ (function () {
    /** The constructor.
     * @param initialPositions The initial positions.
     * @param rotations The initial rotations. ??? Deg/Rad?
     * @param fixPoint The fix point around which we will rotate.
     */
    function RotationOperation(initialPositions, rotations, fixPoint) {
        this.initialPositions = initialPositions.slice(0);
        this.initialRotations = rotations.slice(0);
        this.lastRotations = this.initialRotations.slice(0);
        this.lastPositions = this.initialPositions.slice(0);
        this.fixPoint = fixPoint;
        this.mainComponentIndex = 0;
    }
    RotationOperation.prototype.makeTransformations = function () {
        var _this = this;
        var result = this.lastPositions.map(function (pos, index) { return ({
            position: pos,
            rotation: _this.lastRotations[index],
        }); });
        return result;
    };
    /**
     * Set the main component index (the one that will affect alignment to the raster).
     * @param index The new main component index
     */
    RotationOperation.prototype.setMainComponentIndex = function (index) {
        if (index < this.initialPositions.length) {
            this.mainComponentIndex = index;
        }
    };
    RotationOperation.prototype.executeStart = function (request) {
        this.lastPositions = this.initialPositions.slice(0);
        this.lastRotations = this.initialRotations.slice(0);
        this.oldAngle = request.angle;
    };
    RotationOperation.prototype.executeMotion = function (request) {
        for (var index = 0; index < this.lastRotations.length; index++) {
            this.applyRotation(request.angle, index);
        }
        var resultTransformations = this.makeTransformations();
        return {
            transformations: resultTransformations,
            isInvalid: false,
            snapMatches: [],
        };
    };
    /**
     * Rotates the i-th object by angle around the fixed point.
     * @param angle The number of angle to rotate. Given in radians.
     * @param i The index of the component that will be considered.
     */
    RotationOperation.prototype.applyRotation = function (angle, i) {
        this.lastRotations[i] = Core.Float3.add(this.lastRotations[i], new Core.Float3(0, angle, 0));
        // adjust position to rotation around the fixed point
        this.lastPositions[i] = Core.LinearAlgebra.AdaptToRotation(angle, this.lastPositions[i], this.fixPoint);
    };
    RotationOperation.prototype.executeEnd = function (request) {
        var tMainRotation = this.lastRotations[this.mainComponentIndex].y;
        var tMainComponentRotation = RotationOperation.rotationRaster *
            Math.round(tMainRotation / RotationOperation.rotationRaster) -
            tMainRotation;
        for (var tI = 0; tI < this.lastRotations.length; tI++) {
            this.applyRotation(tMainComponentRotation, tI);
        }
        var resultTransformations = this.makeTransformations();
        return {
            transformations: resultTransformations,
            isInvalid: false,
            snapMatches: [],
        };
    };
    /** The raster to which we align the rotation. Given in radians. */
    RotationOperation.rotationRaster = 15 * Core.Deg2Rad;
    return RotationOperation;
}());
export { RotationOperation };
