import { Constants } from "../Constants";
import { ThreeUtils } from "../utils";
export class AlNode {
    static get Object() {
        return {
            schema: {
                target: { type: "vec3" },
                scale: { type: "number", default: 1 },
                selected: { type: "boolean" },
                nodesEnabled: { type: "boolean" }
            },
            bindListeners() {
                this.elMouseDown = this.elMouseDown.bind(this);
                this.canvasMouseUp = this.canvasMouseUp.bind(this);
                this.elRaycasterIntersected = this.elRaycasterIntersected.bind(this);
                this.elRaycasterIntersectedCleared = this.elRaycasterIntersectedCleared.bind(this);
            },
            addListeners() {
                this.el.addEventListener("mousedown", this.elMouseDown, {
                    capture: false,
                    once: false,
                    passive: true
                });
                this.el.sceneEl.canvas.addEventListener("mouseup", this.canvasMouseUp, {
                    capture: false,
                    once: false,
                    passive: true
                });
                this.el.addEventListener("raycaster-intersected", this.elRaycasterIntersected, { capture: false, once: false, passive: true });
                this.el.addEventListener("raycaster-intersected-cleared", this.elRaycasterIntersectedCleared, { capture: false, once: false, passive: true });
            },
            removeListeners() {
                this.el.removeEventListener("mousedown", this.elMouseDown);
                this.el.removeEventListener("mouseup", this.canvasMouseUp);
                this.el.removeEventListener("raycaster-intersected", this.elRaycasterIntersected);
                this.el.removeEventListener("raycaster-intersected-cleared", this.elRaycasterIntersectedCleared);
            },
            elMouseDown(_event) {
                this.el.sceneEl.emit(AlNodeEvents.SELECTED, { id: this.el.id }, true);
                if (this.data.nodesEnabled) {
                    let state = this.state;
                    state.mouseDown = true;
                    this.el.sceneEl.emit(AlNodeEvents.CONTROLS_DISABLED, {}, true);
                }
            },
            canvasMouseUp(_event) {
                if (this.data.nodesEnabled) {
                    let state = this.state;
                    state.dragging = false;
                    state.mouseDown = false;
                    this.el.sceneEl.emit(AlNodeEvents.CONTROLS_ENABLED, {}, true);
                }
            },
            elRaycasterIntersected(_event) {
                let state = this.state;
                state.hovered = true;
                this.el.sceneEl.emit(AlNodeEvents.INTERSECTION, { id: this.el.id }, true);
            },
            elRaycasterIntersectedCleared(_event) {
                let state = this.state;
                state.hovered = false;
                if (state.mouseDown && state.selected) {
                    state.dragging = true;
                }
                this.el.sceneEl.emit(AlNodeEvents.INTERSECTION_CLEARED, {}, true);
            },
            init() {
                this.tickFunction = AFRAME.utils.throttle(this.tickFunction, Constants.minFrameMS, this);
                this.bindListeners();
                this.addListeners();
                const data = this.data;
                let el = this.el;
                const camera = el.sceneEl.camera.el.object3DMap.camera;
                const geometry = new THREE.SphereGeometry(data.scale, 16, 16);
                let material = new THREE.MeshBasicMaterial();
                const mesh = new THREE.Mesh(geometry, material);
                el.setObject3D("mesh", mesh);
                let targetPos = ThreeUtils.objectToVector3(data.target);
                this.state = {
                    selected: true,
                    hovered: false,
                    geometry,
                    material,
                    mesh,
                    camera,
                    target: targetPos,
                    dragging: false
                };
            },
            update() {
                let state = this.state;
                state.target = this.data.target;
                state.selected = this.data.selected;
            },
            tickFunction() {
                let state = this.state;
                if (this.data.nodesEnabled && state.dragging) {
                    this.el.sceneEl.emit(AlNodeEvents.DRAGGING, { id: this.el.id }, true);
                }
                if (state.hovered || state.dragging) {
                    state.material.color = new THREE.Color(Constants.nodeColors.hovered);
                }
                else if (state.selected) {
                    state.material.color = new THREE.Color(Constants.nodeColors.selected);
                }
                else {
                    state.material.color = new THREE.Color(Constants.nodeColors.normal);
                }
            },
            tick() {
                this.tickFunction();
            },
            remove() {
                this.removeListeners();
                this.el.removeObject3D("mesh");
            }
        };
    }
    static get Tag() {
        return "al-node";
    }
}
export class AlNodeEvents {
}
AlNodeEvents.SELECTED = "al-node-selected";
AlNodeEvents.INTERSECTION = "al-node-intersection";
AlNodeEvents.INTERSECTION_CLEARED = "al-node-intersection-cleared";
AlNodeEvents.DRAGGING = "al-node-dragging";
AlNodeEvents.CONTROLS_ENABLED = "al-controls-enabled";
AlNodeEvents.CONTROLS_DISABLED = "al-controls-disabled";
AlNodeEvents.ANIMATION_STARTED = "al-animation-started";
