import { Vector3 } from 'three';
import type { Viewer } from './Viewer';

/**
 * 材质编辑器的场景鼠标控制.
 */
export class MaterialEditorCameraControl {
    private Viewer: Viewer;

    private _movement: Vector3 = new Vector3();
    private _MouseIsDown: boolean = false;
    private pointId: number;

    private _target: Vector3 | null = null;

    get Target() { return this._target; }
    set Target(val: Vector3 | null) { this._target = val; }

    constructor(view: Viewer, target: Vector3 | null = null) {
        this.Viewer = view;
        this.Target = target;
        this.initMouseControl();
    }

    initMouseControl() {
        let el = this.Viewer.Renderer.domElement;
        el.addEventListener("pointerdown", (e) => { this.pointId = e.pointerId; }, false);
        el.addEventListener("mousedown", this.onMouseDown, false);
        el.addEventListener("mousemove", this.onMouseMove, false);
        el.addEventListener("mouseup", this.onMouseUp, false);
        el.addEventListener('wheel', this.onMouseWheel, false);
    }
    onMouseDown = (event: MouseEvent) => {
        this.requestPointerLock();
        this._MouseIsDown = true;
    };
    onMouseUp = (event: MouseEvent) => {
        this._MouseIsDown = false;
        this.exitPointerLock();
    };
    onMouseMove = (event: MouseEvent) => {
        event.preventDefault();
        if (this._MouseIsDown) {

            this._movement.set(event.movementX, event.movementY, 0);
            if (this.Target) {
                this.Viewer.RotateAround(this._movement, this.Target);
            }
            else this.Viewer.Rotate(this._movement);
        }
    };
    onMouseWheel = (event: WheelEvent) =>
    {
        if (event.deltaY < 0)
        {
            this.Viewer.Zoom(0.6);
        }
        else if (event.deltaY > 0)
        {
            this.Viewer.Zoom(1.4);
        }
    };

    requestPointerLock() {
        const dom = this.Viewer.Renderer.domElement;
        if (dom.setPointerCapture)
            dom.setPointerCapture(this.pointId);

        if (dom.requestPointerLock)
            dom.requestPointerLock();
    }

    exitPointerLock() {
        const dom = this.Viewer.Renderer.domElement;
        if (dom.releasePointerCapture && this.pointId !== undefined) {
            try {
                dom.releasePointerCapture(this.pointId);
            }
            catch (error) { }
        }

        if (document.exitPointerLock)
            document.exitPointerLock();
    }
}
