"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RayPanScaleTransformUC = void 0;
exports.makeRayPanScaleTransformUC = makeRayPanScaleTransformUC;
const core_1 = require("@vived/core");
const core_2 = require("@vived/core");
const Babylon_1 = require("../../Babylon");
const Dispatcher_1 = require("../../Dispatcher");
const Entities_1 = require("../Entities");
class RayPanScaleTransformUC extends core_1.AppObjectUC {
}
exports.RayPanScaleTransformUC = RayPanScaleTransformUC;
RayPanScaleTransformUC.type = "RayPanScaleTransformUC";
function makeRayPanScaleTransformUC(appObject) {
    return new RayPanScaleTransformUCImp(appObject);
}
class RayPanScaleTransformUCImp extends RayPanScaleTransformUC {
    updatePosition(pick) {
        if (!this.transform)
            return;
        const originalPickOffset = this.transform.localPointToWorld(this.pickOffset);
        const movement = core_2.Vector3.Subtract(pick, originalPickOffset);
        let wPos = core_2.Vector3.Add(movement, this.transform.worldPosition);
        if (this.minX !== undefined && wPos.x < this.minX) {
            wPos = new core_2.Vector3(this.minX, wPos.y, wPos.z);
        }
        if (this.maxX !== undefined && wPos.x > this.maxX) {
            wPos = new core_2.Vector3(this.maxX, wPos.y, wPos.z);
        }
        if (this.minY !== undefined && wPos.y < this.minY) {
            wPos = new core_2.Vector3(wPos.x, this.minY, wPos.z);
        }
        if (this.maxY !== undefined && wPos.y > this.maxY) {
            wPos = new core_2.Vector3(wPos.x, this.maxY, wPos.z);
        }
        this.transform.worldPosition = wPos;
    }
    updateScale(ray, pick) {
        if (!this.transform)
            return;
        const rayLength = core_2.ParametricLine.GetDistanceToPoint(ray, pick);
        const rayDelta = rayLength - this.lastRayLength;
        const localPickOffset = this.transform.worldPointToLocal(pick);
        const currentScale = this.transform.worldScale.x;
        const scaleDelta = rayDelta * this.sensitivity * currentScale;
        let newScale = currentScale + scaleDelta;
        if (this.minScale !== undefined && newScale < this.minScale) {
            newScale = this.minScale;
        }
        if (this.maxScale !== undefined && newScale > this.maxScale) {
            newScale = this.maxScale;
        }
        this.transform.worldScale = new core_2.Vector3(newScale, newScale, newScale);
        const worldPickOffset = this.transform.localPointToWorld(localPickOffset);
        const bump = core_2.Vector3.Subtract(pick, worldPickOffset);
        this.transform.worldPosition = core_2.Vector3.Add(bump, this.transform.worldPosition);
        this.lastRayLength = rayLength;
    }
    constructor(appObject) {
        super(appObject, RayPanScaleTransformUC.type);
        this.enabled = true;
        this.sensitivity = 1;
        this.allowUpdate = false;
        this.initialScale = 1;
        this.pickOffset = core_2.Vector3.Zero();
        this._panPlane = core_2.ParametricPlane.XY();
        this.lastRayLength = 0;
        this.initialize = (ray) => {
            this.allowUpdate = false;
            if (!this.transform)
                return;
            if (this.pickPlane) {
                this._panPlane = this.pickPlane;
            }
            else {
                const pick = (0, Babylon_1.sceneRayPick)(ray, this.appObjects);
                this._panPlane = core_2.ParametricPlane.FromPointNormal(pick?.worldPickPoint ?? core_2.Vector3.Zero(), core_2.Vector3.Backward());
            }
            const pickPoint = this._panPlane.intersectLine(ray) ?? core_2.Vector3.Zero();
            this.lastRayLength = core_2.ParametricLine.GetDistanceToPoint(ray, pickPoint);
            this.pickOffset = this.transform.worldPointToLocal(pickPoint);
            this.initialScale = this.transform.worldScale.x;
            this.allowUpdate = true;
        };
        this.update = (ray) => {
            if (!this.enabled)
                return;
            if (!this.allowUpdate)
                return;
            if (!this.transform)
                return;
            const pick = this._panPlane.intersectLine(ray) ?? core_2.Vector3.Zero();
            this.updateScale(ray, pick);
            this.updatePosition(pick);
        };
        this.finish = () => {
            if (!this.transform)
                return;
            if (!this.allowUpdate)
                return;
            if (this.initialScale !== this.transform.worldScale.x) {
                (0, Dispatcher_1.dispatchStateChange)(this.appObjects);
            }
            this.allowUpdate = false;
        };
        this.transform = appObject.getComponent(Entities_1.Transform3D.type);
        if (!this.transform) {
            this.error("App Object does not have a Transform3D Entity");
        }
    }
}
//# sourceMappingURL=RayPanScaleTransform.js.map