import { __decorate } from "../../tslib.es6.js";
import { serialize } from "../../Misc/decorators.js";
import { CameraInputTypes } from "../cameraInputsManager.js";
import { KeyboardEventTypes } from "../../Events/keyboardEvents.js";
import { Tools } from "../../Misc/tools.js";
/**
 * Manage the keyboard inputs to control the movement of a geospatial camera.
 * @see https://doc.babylonjs.com/features/featuresDeepDive/cameras/customizingCameraInputs
 */
export class GeospatialCameraKeyboardInput {
    constructor() {
        /**
         * Defines the list of key codes associated with the up action (pan up)
         */
        this.keysUp = [38];
        /**
         * Defines the list of key codes associated with the down action (pan down)
         */
        this.keysDown = [40];
        /**
         * Defines the list of key codes associated with the left action (pan left)
         */
        this.keysLeft = [37];
        /**
         * Defines the list of key codes associated with the right action (pan right)
         */
        this.keysRight = [39];
        /**
         * Defines the list of key codes associated with zoom in (+ or =)
         */
        this.keysZoomIn = [187, 107]; // 187 = + key, 107 = numpad +
        /**
         * Defines the list of key codes associated with zoom out (-)
         */
        this.keysZoomOut = [189, 109]; // 189 = - key, 109 = numpad -
        /**
         * Defines the rotation sensitivity of the inputs.
         * (How many pixels of pointer input to apply per keypress, before rotation speed factor is applied by movement class)
         */
        this.rotationSensitivity = 1.0;
        /**
         * Defines the panning sensitivity of the inputs.
         * (How many pixels of pointer input to apply per keypress, before pan speed factor is applied by movement class)
         */
        this.panSensitivity = 1.0;
        /**
         * Defines the zooming sensitivity of the inputs.
         * (How many pixels of pointer input to apply per keypress, before zoom speed factor is applied by movement class)
         */
        this.zoomSensitivity = 1.0;
        this._keys = new Array();
    }
    /**
     * Attach the input controls to a specific dom element to get the input from.
     * @param noPreventDefault Defines whether event caught by the controls should call preventdefault() (https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault)
     */
    attachControl(noPreventDefault) {
        // was there a second variable defined?
        noPreventDefault = Tools.BackCompatCameraNoPreventDefault(arguments);
        if (this._onCanvasBlurObserver) {
            return;
        }
        this._onCanvasBlurObserver = this._engine.onCanvasBlurObservable.add(() => {
            this._keys.length = 0;
        });
        this._onKeyboardObserver = this._scene.onKeyboardObservable.add((info) => {
            const evt = info.event;
            if (!evt.metaKey) {
                if (info.type === KeyboardEventTypes.KEYDOWN) {
                    this._ctrlPressed = evt.ctrlKey;
                    if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
                        this.keysDown.indexOf(evt.keyCode) !== -1 ||
                        this.keysLeft.indexOf(evt.keyCode) !== -1 ||
                        this.keysRight.indexOf(evt.keyCode) !== -1 ||
                        this.keysZoomIn.indexOf(evt.keyCode) !== -1 ||
                        this.keysZoomOut.indexOf(evt.keyCode) !== -1) {
                        const index = this._keys.indexOf(evt.keyCode);
                        if (index === -1) {
                            this._keys.push(evt.keyCode);
                        }
                        if (evt.preventDefault) {
                            if (!noPreventDefault) {
                                evt.preventDefault();
                            }
                        }
                    }
                }
                else {
                    if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
                        this.keysDown.indexOf(evt.keyCode) !== -1 ||
                        this.keysLeft.indexOf(evt.keyCode) !== -1 ||
                        this.keysRight.indexOf(evt.keyCode) !== -1 ||
                        this.keysZoomIn.indexOf(evt.keyCode) !== -1 ||
                        this.keysZoomOut.indexOf(evt.keyCode) !== -1) {
                        const index = this._keys.indexOf(evt.keyCode);
                        if (index >= 0) {
                            this._keys.splice(index, 1);
                        }
                        if (evt.preventDefault) {
                            if (!noPreventDefault) {
                                evt.preventDefault();
                            }
                        }
                    }
                }
            }
        });
    }
    /**
     * Detach the current controls from the specified dom element.
     */
    detachControl() {
        if (this._scene) {
            if (this._onKeyboardObserver) {
                this._scene.onKeyboardObservable.remove(this._onKeyboardObserver);
            }
            if (this._onCanvasBlurObserver) {
                this._engine.onCanvasBlurObservable.remove(this._onCanvasBlurObserver);
            }
            this._onKeyboardObserver = null;
            this._onCanvasBlurObserver = null;
        }
        this._keys.length = 0;
    }
    /**
     * Update the current camera state depending on the inputs that have been used this frame.
     * This is a dynamically created lambda to avoid the performance penalty of looping for inputs in the render loop.
     */
    checkInputs() {
        if (this._onKeyboardObserver) {
            const camera = this.camera;
            for (let index = 0; index < this._keys.length; index++) {
                const keyCode = this._keys[index];
                if (this._ctrlPressed) {
                    // Rotation
                    if (this.keysLeft.indexOf(keyCode) !== -1) {
                        camera.movement.rotationAccumulatedPixels.y -= this.rotationSensitivity;
                    }
                    else if (this.keysRight.indexOf(keyCode) !== -1) {
                        camera.movement.rotationAccumulatedPixels.y += this.rotationSensitivity;
                    }
                    else if (this.keysUp.indexOf(keyCode) !== -1) {
                        camera.movement.rotationAccumulatedPixels.x -= this.rotationSensitivity;
                    }
                    else if (this.keysDown.indexOf(keyCode) !== -1) {
                        camera.movement.rotationAccumulatedPixels.x += this.rotationSensitivity;
                    }
                }
                else {
                    // Zoom
                    if (this.keysZoomIn.indexOf(keyCode) !== -1) {
                        camera.movement.zoomAccumulatedPixels += this.zoomSensitivity;
                    }
                    else if (this.keysZoomOut.indexOf(keyCode) !== -1) {
                        camera.movement.zoomAccumulatedPixels -= this.zoomSensitivity;
                    }
                    else {
                        // Call into movement class handleDrag so that behavior matches that of pointer input, simulating drag from center of screen
                        const centerX = this._engine.getRenderWidth() / 2;
                        const centerY = this._engine.getRenderHeight() / 2;
                        camera.movement.startDrag(centerX, centerY);
                        if (this.keysLeft.indexOf(keyCode) !== -1) {
                            camera.movement.handleDrag(centerX - this.panSensitivity, centerY);
                        }
                        else if (this.keysRight.indexOf(keyCode) !== -1) {
                            camera.movement.handleDrag(centerX + this.panSensitivity, centerY);
                        }
                        else if (this.keysUp.indexOf(keyCode) !== -1) {
                            camera.movement.handleDrag(centerX, centerY + this.panSensitivity);
                        }
                        else if (this.keysDown.indexOf(keyCode) !== -1) {
                            camera.movement.handleDrag(centerX, centerY - this.panSensitivity);
                        }
                        camera.movement.stopDrag();
                    }
                }
            }
        }
    }
    /**
     * Gets the class name of the current input.
     * @returns the class name
     */
    getClassName() {
        return "GeospatialCameraKeyboardInput";
    }
    /**
     * Get the friendly name associated with the input class.
     * @returns the input friendly name
     */
    getSimpleName() {
        return "keyboard";
    }
}
__decorate([
    serialize()
], GeospatialCameraKeyboardInput.prototype, "keysUp", void 0);
__decorate([
    serialize()
], GeospatialCameraKeyboardInput.prototype, "keysDown", void 0);
__decorate([
    serialize()
], GeospatialCameraKeyboardInput.prototype, "keysLeft", void 0);
__decorate([
    serialize()
], GeospatialCameraKeyboardInput.prototype, "keysRight", void 0);
__decorate([
    serialize()
], GeospatialCameraKeyboardInput.prototype, "keysZoomIn", void 0);
__decorate([
    serialize()
], GeospatialCameraKeyboardInput.prototype, "keysZoomOut", void 0);
__decorate([
    serialize()
], GeospatialCameraKeyboardInput.prototype, "rotationSensitivity", void 0);
__decorate([
    serialize()
], GeospatialCameraKeyboardInput.prototype, "panSensitivity", void 0);
__decorate([
    serialize()
], GeospatialCameraKeyboardInput.prototype, "zoomSensitivity", void 0);
CameraInputTypes["GeospatialCameraKeyboardInput"] = GeospatialCameraKeyboardInput;
//# sourceMappingURL=geospatialCameraKeyboardInput.js.map