'use strict';

import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
    static targets = ["input", "display"];

    connect() {
        this.syncDisplay();
    }

    decrement() {
        this.updateValue(-1);
    }

    increment() {
        this.updateValue(1);
    }

    syncDisplay() {
        const value = this.parseValue(this.inputTarget.value);

        this.displayTargets.forEach((displayTarget) => {
            displayTarget.textContent = value;
        });
    }

    updateValue(direction) {
        if (this.inputTarget.disabled) {
            return;
        }

        if (typeof this.inputTarget.stepUp === 'function' && typeof this.inputTarget.stepDown === 'function') {
            if (direction > 0) {
                this.inputTarget.stepUp();
            } else {
                this.inputTarget.stepDown();
            }
        } else {
            const currentValue = this.parseValue(this.inputTarget.value);
            const step = this.parseStep(this.inputTarget.step);
            const min = this.parseBound(this.inputTarget.min);
            const max = this.parseBound(this.inputTarget.max);

            let nextValue = currentValue + (direction * step);

            if (min !== null) {
                nextValue = Math.max(min, nextValue);
            }

            if (max !== null) {
                nextValue = Math.min(max, nextValue);
            }

            this.inputTarget.value = `${nextValue}`;
        }

        this.syncDisplay();
        this.dispatchFieldEvents();
    }

    dispatchFieldEvents() {
        this.inputTarget.dispatchEvent(new Event('input', { bubbles: true }));
        this.inputTarget.dispatchEvent(new Event('change', { bubbles: true }));
    }

    parseValue(value) {
        const parsedValue = Number.parseInt(value, 10);

        if (Number.isNaN(parsedValue) || parsedValue < 1) {
            return 1;
        }

        return parsedValue;
    }

    parseStep(step) {
        const parsedStep = Number.parseInt(step, 10);

        if (Number.isNaN(parsedStep) || parsedStep < 1) {
            return 1;
        }

        return parsedStep;
    }

    parseBound(bound) {
        const parsedBound = Number.parseInt(bound, 10);

        if (Number.isNaN(parsedBound)) {
            return null;
        }

        return parsedBound;
    }
}
