export class Controls {
    constructor() {
        this.keys = {};
        this.mouse = {
            x: 0,
            y: 0,
            buttons: {
                left: false,
                middle: false,
                right: false
            },
            pressed: {
                left: false,
                middle: false,
                right: false
            },
            released: {
                left: false,
                middle: false,
                right: false
            },
            wheel: {
                deltaX: 0,
                deltaY: 0,
                deltaZ: 0
            }
        };
        this.setupEventListeners();
    }

    setupEventListeners() {
        window.addEventListener('keydown', (e) => {
            this.keys[e.key] = true;
        });
        window.addEventListener('keyup', (e) => {
            this.keys[e.key] = false;
        });
        window.addEventListener('mousemove', (e) => {
            this.mouse.x = e.clientX;
            this.mouse.y = e.clientY;
        });
        window.addEventListener('mousedown', (e) => {
            if (e.button === 1) {
                e.preventDefault();
            }
            this.setMouseButtonState(e.button, true);
        });
        window.addEventListener('mouseup', (e) => {
            this.setMouseButtonState(e.button, false);
        });
        window.addEventListener('auxclick', (e) => {
            e.preventDefault();
        });
        window.addEventListener('contextmenu', (e) => {
            e.preventDefault();
        });
        window.addEventListener('wheel', (e) => {
            e.preventDefault();
            this.mouse.wheel.deltaX += e.deltaX;
            this.mouse.wheel.deltaY += e.deltaY;
            this.mouse.wheel.deltaZ += e.deltaZ;
        }, { passive: false });
    }

    setMouseButtonState(button, isPressed) {
        const buttonName = this.getMouseButtonName(button);
        if (!buttonName || this.mouse.buttons[buttonName] === isPressed) {
            return;
        }

        this.mouse.buttons[buttonName] = isPressed;
        if (isPressed) {
            this.mouse.pressed[buttonName] = true;
        } else {
            this.mouse.released[buttonName] = true;
        }
    }

    getMouseButtonName(button) {
        if (button === 0 || button === 'left') {
            return 'left';
        }
        if (button === 1 || button === 'middle') {
            return 'middle';
        }
        if (button === 2 || button === 'right') {
            return 'right';
        }
        return null;
    }

    wasMousePressed(button) {
        const buttonName = this.getMouseButtonName(button);
        return buttonName ? this.mouse.pressed[buttonName] : false;
    }

    wasMouseReleased(button) {
        const buttonName = this.getMouseButtonName(button);
        return buttonName ? this.mouse.released[buttonName] : false;
    }

    resetMouseTransitions() {
        this.mouse.pressed.left = false;
        this.mouse.pressed.middle = false;
        this.mouse.pressed.right = false;
        this.mouse.released.left = false;
        this.mouse.released.middle = false;
        this.mouse.released.right = false;
    }

    resetMouseWheel() {
        this.mouse.wheel.deltaX = 0;
        this.mouse.wheel.deltaY = 0;
        this.mouse.wheel.deltaZ = 0;
    }

    resetFrameState() {
        this.resetMouseTransitions();
        this.resetMouseWheel();
    }

    resetInputState() {
        this.keys = {};
        this.mouse.buttons.left = false;
        this.mouse.buttons.middle = false;
        this.mouse.buttons.right = false;
        this.resetMouseTransitions();
        this.resetMouseWheel();
    }
}

export const controls = new Controls();