import { AppObjectEntity, generateUniqueID, MemoizedNumber, MemoizedQuaternion, MemoizedString, MemoizedVector3, Quaternion, Vector3, } from "@vived/core";
import { EnablementEntity } from "../../Enablement";
import { makeChannelModelObject, } from "./ChannelModelObject";
export var ChannelModelState;
(function (ChannelModelState) {
    ChannelModelState["INIT"] = "Initialized";
    ChannelModelState["LOADING"] = "Loading";
    ChannelModelState["READY"] = "Ready";
    ChannelModelState["ERROR"] = "Error";
})(ChannelModelState || (ChannelModelState = {}));
export class ChannelModelEntity extends AppObjectEntity {
    static get(id, appObjects) {
        const appObject = appObjects.get(id);
        if (!appObject) {
            appObjects.submitWarning("ChannelModel.get", "Unable to find app object by ID");
            return;
        }
        return appObject.getComponent(ChannelModelEntity.type);
    }
}
ChannelModelEntity.type = "ChannelModelEntity";
export function makeChannelModelEntity(appObject) {
    return new ChannelModelEntityImp(appObject);
}
class ChannelModelEntityImp extends ChannelModelEntity {
    get id() {
        return this.appObject.id;
    }
    get name() {
        return this._name.val;
    }
    set name(name) {
        this._name.val = name;
    }
    get bounds_min() {
        return this._boundsMin.val;
    }
    set bounds_min(bounds_min) {
        this._boundsMin.val = bounds_min;
    }
    get bounds_max() {
        return this._boundsMax.val;
    }
    set bounds_max(bounds_max) {
        this._boundsMax.val = bounds_max;
    }
    get defaultPosition() {
        return this._defaultPosition.val;
    }
    set defaultPosition(position) {
        this._defaultPosition.val = position;
    }
    get defaultRotation() {
        return this._defaultRotation.val;
    }
    set defaultRotation(rotation) {
        this._defaultRotation.val = rotation;
    }
    get defaultScale() {
        return this._defaultScale.val;
    }
    set defaultScale(scale) {
        this._defaultScale.val = scale;
    }
    get rootRotation() {
        return this._rootRotation.val;
    }
    set rootRotation(rotation) {
        this._rootRotation.val = rotation;
    }
    get state() {
        return this._state.val;
    }
    set state(val) {
        this._state.val = val;
    }
    get modelError() {
        return this._error;
    }
    set modelError(val) {
        this._error = val;
        this._state.val = ChannelModelState.ERROR;
    }
    get enabled() {
        return this.enablement.enabled;
    }
    set enabled(val) {
        this.enablement.enabled = val;
    }
    get modelObjectIds() {
        return Array.from(this.modelObjectLookup.keys());
    }
    get data() {
        const modelObjects = Array.from(this.modelObjectLookup.values());
        const objects = modelObjects.map((obj) => {
            return {
                id: obj.id,
                label: obj.label.default,
                meshPaths: [...obj.subMeshPaths],
                tags: [...obj.tags],
            };
        });
        return {
            bounds_max: this._boundsMax.val.dto,
            bounds_min: this._boundsMin.val.dto,
            defaultPosition: this._defaultPosition.val.dto,
            defaultRotation: this._defaultRotation.val.dto,
            defaultScale: this._defaultScale.val,
            name: this._name.val,
            objects,
            version: 1,
            originalCollectionID: this.originalCollectionID,
            rootRotation: this._rootRotation.val.dto,
        };
    }
    constructor(appObject) {
        super(appObject, ChannelModelEntity.type);
        this._name = new MemoizedString("", this.notifyOnChange);
        this._boundsMin = new MemoizedVector3(Vector3.Zero(), this.notifyOnChange);
        this._boundsMax = new MemoizedVector3(Vector3.Zero(), this.notifyOnChange);
        this._defaultPosition = new MemoizedVector3(Vector3.Zero(), this.notifyOnChange);
        this._defaultRotation = new MemoizedQuaternion(Quaternion.Identity(), this.notifyOnChange);
        this._defaultScale = new MemoizedNumber(1, this.notifyOnChange);
        this._rootRotation = new MemoizedQuaternion(Quaternion.Identity(), this.notifyOnChange);
        this._state = new MemoizedString(ChannelModelState.INIT, this.notifyOnChange);
        this.modelObjectLookup = new Map();
        this.modelObjectFactory = (id) => {
            const ao = this.appObjects.getOrCreate(id);
            return makeChannelModelObject(ao);
        };
        this.addModelObject = (id) => {
            const idToUse = id ?? generateUniqueID();
            const obj = this.modelObjectFactory(idToUse);
            this.modelObjectLookup.set(idToUse, obj);
            obj.addChangeObserver(this.notifyOnChange);
            this.notifyOnChange();
            return obj;
        };
        this.getModelObject = (id) => {
            return this.modelObjectLookup.get(id);
        };
        this.hasModelObject = (id) => {
            return this.modelObjectLookup.has(id);
        };
        this.modelObjects = () => {
            return Array.from(this.modelObjectLookup.values());
        };
        this.setupFromData = (data) => {
            if ("bounds_max" in data) {
                this.bounds_max = Vector3.FromDTO(data.bounds_max);
            }
            else {
                this.bounds_max = Vector3.Zero();
            }
            if ("bounds_min" in data) {
                this.bounds_min = Vector3.FromDTO(data.bounds_min);
            }
            else {
                this.bounds_min = Vector3.Zero();
            }
            if ("defaultPosition" in data) {
                this.defaultPosition = Vector3.FromDTO(data.defaultPosition);
            }
            else {
                this.defaultPosition = Vector3.Zero();
            }
            if ("defaultRotation" in data) {
                this.defaultRotation = Quaternion.FromDTO(data.defaultRotation);
            }
            else {
                this.defaultRotation = Quaternion.Identity();
            }
            if ("rootRotation" in data) {
                this.rootRotation = Quaternion.FromDTO(data.rootRotation);
            }
            else {
                this.rootRotation = Quaternion.Identity();
            }
            if ("defaultScale" in data) {
                this.defaultScale = data.defaultScale;
            }
            else {
                this.defaultScale = 1;
            }
            if ("name" in data) {
                this.name = data.name;
            }
            else {
                this.name = "Unnamed Channel";
            }
            if ("originalCollectionID" in data) {
                this.originalCollectionID = data.originalCollectionID;
            }
            if ("objects" in data) {
                const objects = data.objects;
                objects.forEach((obj) => {
                    if ("id" in obj) {
                        const modelObj = this.addModelObject(obj.id);
                        if ("label" in obj) {
                            modelObj.label.default = obj.label;
                        }
                        if ("meshPaths" in obj) {
                            modelObj.subMeshPaths = obj.meshPaths;
                        }
                        if ("tags" in obj) {
                            modelObj.tags = obj.tags;
                        }
                    }
                });
            }
        };
        this.enablement = EnablementEntity.addIfMissing(appObject);
        this.enablement.addChangeObserver(this.notifyOnChange);
    }
}
//# sourceMappingURL=ChannelModel.js.map