import { onPageLoadComplete, fireEvent } from '@nimius/event-utility';

/**
 * ## Amount selection
 *
 * Allows an input to be controlled by 'plus' and 'minus' buttons next to it.
 * The amount of one step can be changed by changing the Stepsize (`step` attribut)
 * of the `input[type=number]` and defaults to 1, if none was given.
 *
 * These buttons will be disabled once the minimum or maximum value of the input
 * is reached. Similar to the Stepsize, these minimum and maximum values can be
 * controlled using the native `min` and `max` attributes of the `input[type=number]`.
 *
 * ### Attributes
 *
 * The following attributes must be used:
 * - `[data-amount-selection]`: Must be added to an element that wraps exactly one amount
 *          selection group. All other attributes listed below are scoped under this wrapper.
 * - `[data-amount-selection.input]`: Indicates the `<input>` Element that is being changed.
 *          The input element should be of the type `number` and should use the `min`, `max`
 *          and `step` attributes.
 * - `[data-amount-selection.increment]`: Indicates the button that increments the input.
 * - `[data-amount-selection.decrement]`: Indicates the button that decrement the input.
 *
 * @example <caption>Simple example</caption>
 * <div data-amount-selection>
 *     <button data-amount-selection.decrement>-</button>
 *     <input type="number"
 *            data-amount-selection.input>
 *     <button data-amount-selection.increment>+</button>
 * </div>
 *
 * @example <caption>Complex example: Custom step, min & max attributes</caption>
 * <div data-amount-selection>
 *     <button data-amount-selection.decrement>-</button>
 *     <input type="number"
 *            min="0"
 *            max="100"
 *            step="2.5"
 *            data-amount-selection.input>
 *     <button data-amount-selection.increment>+</button>
 * </div>
 */
onPageLoadComplete(() => {
    for (const wrapper of document.querySelectorAll('[data-amount-selection]')) {

        /**
         * The input that is being modified.
         * @type {HTMLInputElement}
         */
        const input = wrapper.querySelector('[data-amount-selection\\.input]');

        /**
         * Button that reduces the value of the input by one.
         * @type {HTMLButtonElement}
         */
        const decrementButton = wrapper.querySelector('[data-amount-selection\\.decrement]');

        /**
         * Button that increases the value of the input by one.
         * @type {HTMLButtonElement}
         */
        const incrementButton = wrapper.querySelector('[data-amount-selection\\.increment]');

        /**
         * The step size that is incremented / decremented by.
         * @type {number}
         */
        const deltaAmount = parseFloat(input.getAttribute('step')) || 1;

        /**
         * Adds the given delta to the current input.
         * Also sets the disabled state on the buttons depending on the current value.
         * @param {int} delta
         */
        const addDelta = delta => {
            input.value = parseFloat(input.value) + delta;

            // The decrement button is disabled, if there is a minimum value and that minimum is reached.
            // The increment button is disabled, if there is a maximum value and that maximum is reached.

            /* eslint-disable */
            decrementButton.disabled = input.hasAttribute('min') && parseInt(input.getAttribute('min')) >= input.value;
            incrementButton.disabled = input.hasAttribute('max') && parseInt(input.getAttribute('max')) <= input.value;
            /* eslint-enable */

            fireEvent(input, 'change');
        };

        // Abort execution, if one of the elements is missing.
        if (!input || !decrementButton || !incrementButton) {
            console.error(`
                Amount Selection: A [data-amount-selection] *must* have the following children:
                [data-amount-selection.input], [data-amount-selection.decrement], [data-amount-selection.increment].
                One of them seem to be missing. Aborting initialization'
            `);
            continue;
        }

        // Attach event listeners.
        decrementButton.addEventListener('click', () => addDelta(-deltaAmount));
        incrementButton.addEventListener('click', () => addDelta(+deltaAmount));

        // Add a delta of 0 in the beginning.
        // This is done to ensure that everything is in a consistent state.
        addDelta(0);
    }
});
