import { AppObjectEntity, getSingletonComponent, ParametricPlane, Vector2, Vector3, } from "@vived/core";
import { Transform3D } from "../../Transform3D";
export var WorkPlaneUnits;
(function (WorkPlaneUnits) {
    WorkPlaneUnits[WorkPlaneUnits["INCHES"] = 0] = "INCHES";
    WorkPlaneUnits[WorkPlaneUnits["METERS"] = 1] = "METERS";
    WorkPlaneUnits[WorkPlaneUnits["FEET"] = 2] = "FEET";
})(WorkPlaneUnits || (WorkPlaneUnits = {}));
export var WorkPlaneShape;
(function (WorkPlaneShape) {
    WorkPlaneShape[WorkPlaneShape["RECTANGLE"] = 0] = "RECTANGLE";
    WorkPlaneShape[WorkPlaneShape["CIRCLE"] = 1] = "CIRCLE";
    WorkPlaneShape[WorkPlaneShape["UNKNOWN"] = 2] = "UNKNOWN";
})(WorkPlaneShape || (WorkPlaneShape = {}));
export class WorkPlaneEntity extends AppObjectEntity {
}
WorkPlaneEntity.type = "WorkPlaneEntity";
WorkPlaneEntity.get = (appObjects) => getSingletonComponent(WorkPlaneEntity.type, appObjects);
export function makeWorkPlaneEntity(appObj) {
    return new WorkPlaneImp(appObj);
}
class WorkPlaneImp extends WorkPlaneEntity {
    get workPlaneRadius() {
        return this._workPlaneRadius;
    }
    get workPlaneSize() {
        return this._workPlaneSize;
    }
    get units() {
        return this._units;
    }
    set units(val) {
        if (val === this._units)
            return;
        this._units = val;
        const scale = 1 / this.conversionFactor;
        this.transform.localScale = new Vector3(scale, scale, scale);
    }
    get workPlaneShape() {
        return this._workPlaneShape;
    }
    get conversionFactor() {
        switch (this.units) {
            case WorkPlaneUnits.FEET:
                return 3.28084;
            case WorkPlaneUnits.INCHES:
                return 39.3701;
            case WorkPlaneUnits.METERS:
                return 1;
            default:
                console.warn("[WorkPlane] Unknown units " + this.units);
                return 1;
        }
    }
    constrainToRadius(workPlanePick) {
        if (!this.workPlaneRadius)
            return workPlanePick;
        const pickRadius = workPlanePick.magnitued;
        if (pickRadius <= this.workPlaneRadius) {
            return workPlanePick;
        }
        else {
            return undefined;
        }
    }
    constrainToSize(workPlanePick) {
        if (!this._workPlaneHalfSize)
            return workPlanePick;
        const x = workPlanePick.x;
        const maxX = this._workPlaneHalfSize.x;
        const minX = -this._workPlaneHalfSize.x;
        const y = workPlanePick.y;
        const maxY = this._workPlaneHalfSize.y;
        const minY = -this._workPlaneHalfSize.y;
        if (x >= minX && x <= maxX && y >= minY && y <= maxY) {
            return workPlanePick;
        }
        else {
            return undefined;
        }
    }
    constructor(appObject) {
        super(appObject, WorkPlaneEntity.type);
        this._workPlaneHalfSize = Vector2.One();
        this.showWorkPlane = true;
        this._units = WorkPlaneUnits.METERS;
        this._workPlaneShape = WorkPlaneShape.UNKNOWN;
        this.setWorkPlaneSize = (size) => {
            this._workPlaneSize = size;
            this._workPlaneHalfSize = new Vector2(0.5 * size.x, 0.5 * size.y);
            this._workPlaneShape = WorkPlaneShape.RECTANGLE;
        };
        this.setWorkPlaneRadius = (radius) => {
            this._workPlaneRadius = radius;
            this._workPlaneShape = WorkPlaneShape.CIRCLE;
        };
        this.pickOnWorkPlane = (ray, unconstrained = false) => {
            const worldPos = this.transform.worldPosition;
            const worldUp = this.transform.localDirectionToWorld(Vector3.Up());
            const pickPlane = ParametricPlane.FromPointNormal(worldPos, worldUp);
            const worldPick = pickPlane.intersectLine(ray);
            if (worldPick === undefined) {
                return undefined;
            }
            const localPick = this.transform.worldPointToLocal(worldPick);
            const workPlanePick = new Vector2(localPick.x, localPick.z);
            if (unconstrained) {
                return workPlanePick;
            }
            if (this._workPlaneShape === WorkPlaneShape.CIRCLE) {
                return this.constrainToRadius(workPlanePick);
            }
            else if (this._workPlaneShape === WorkPlaneShape.RECTANGLE) {
                return this.constrainToSize(workPlanePick);
            }
            else {
                return workPlanePick;
            }
        };
        this.transform = Transform3D.addIfMissing(appObject);
        this.transform.addChangeObserver(this.notifyOnChange);
    }
}
//# sourceMappingURL=WorkPlaneEntity.js.map