import { attributeSelector } from './selector-utilities';
import { fireEvent } from '@nimius/event-utility';

const ATTRIBUTE = Object.freeze({
    TOGGLE_BUTTON: 'data-toubiz-results-list.filter-group-toggle',
    RESET_BUTTON: 'data-toubiz-results-list.filter-group-reset',
    APPLY_BUTTON: 'data-toubiz-results-list.filter-group-apply',
    FILTER_GROUP_ITEM: 'data-toubiz-results-list.filter-group-item',
    FILTER_GROUP_ITEM_RESET_EVENT: 'data-toubiz-results-list.filter-group-item-reset-event',
});

export class ResultsListFilterGroup {

    /**
     * @param {HTMLElement} wrapper
     */
    constructor(wrapper) {
        this.wrapper = wrapper;
        this.items = wrapper.querySelectorAll(attributeSelector(ATTRIBUTE.FILTER_GROUP_ITEM));

        // button elements
        this.resetButton = wrapper.querySelector(attributeSelector(ATTRIBUTE.RESET_BUTTON));
        this.applyButton = wrapper.querySelector(attributeSelector(ATTRIBUTE.APPLY_BUTTON));
        this.toggleButton = wrapper.querySelector(attributeSelector(ATTRIBUTE.TOGGLE_BUTTON));

        // set initial state
        this.state = this.getCurrentState();

        // initialize button listeners and disabled state toggling
        if (this.resetButton && this.applyButton) {
            this.initializeButtons();
        }
    }

    getItemValue(input) {
        switch(input.type) {
            case 'checkbox':
                return input.checked;
            case 'text':
            case 'number':
                return input.value;
            default:
                return null;
        }
    }

    resetItemValue(input) {
        const resetEvent = input.getAttribute(ATTRIBUTE.FILTER_GROUP_ITEM_RESET_EVENT);

        if (resetEvent) {
            fireEvent(input, resetEvent);
        }

        switch(input.type) {
            case 'checkbox':
                input.checked = false;
                break;
            case 'text':
            case 'number':
                input.value = null;
                break;
            default:
                break;
        }
    }

    reset() {
        for (const item of this.items) {
            this.resetItemValue(item);
        }
    }

    getCurrentState() {
        const currentState = [];

        for (const item of this.items) {
            currentState.push(this.getItemValue(item));
        }

        return currentState;
    }

    updateState() {
        this.state = this.getCurrentState();
    }

    hasUnappliedChanges() {
        const previousState = JSON.stringify(this.state);
        const currentState = JSON.stringify(this.getCurrentState());

        return previousState !== currentState;
    }

    maybeCloseOverlay() {
        if (this.toggleButton) {
            fireEvent(this.toggleButton, 'target-enhancement.close');
        }
    }

    onResetIntent() {
        this.reset();
        this.updateState();
        this.resetButton.disabled = true;
        this.applyButton.disabled = true;

        fireEvent(this.wrapper, 'filter-group.reset');
    }

    update() {
        this.updateState();
        this.applyButton.disabled = true;
    }

    apply() {
        this.update();
        this.maybeCloseOverlay();

        fireEvent(this.wrapper, 'filter-group.apply');
    }

    onClose() {
        if (this.hasUnappliedChanges()) {
            this.reset();
            this.updateState();
            this.resetButton.disabled = true;
            this.applyButton.disabled = true;
        }
    }

    hasActiveItems() {
        let hasActiveItems = false;

        for (const item of this.state) {
            if (item && item !== '') {
                hasActiveItems = true;
            }
        }

        return hasActiveItems;
    }

    onItemChanged(item) {
        if (this.getItemValue(item)) {
            this.resetButton.disabled = false;
        } else if (!this.hasActiveItems()) {
            this.resetButton.disabled = true;
        }

        this.applyButton.disabled = false;
    }

    initializeButtons() {
        for (const item of this.items) {
            if (this.getItemValue(item)) {
                this.resetButton.disabled = false;
            }

            item.addEventListener('change', () => this.onItemChanged(item));
            item.addEventListener('results-list-filter.change', () => this.onItemChanged(item));
        }

        this.resetButton.addEventListener('click', () => {
            this.onResetIntent();
            this.maybeCloseOverlay();
        });

        this.applyButton.addEventListener('click', () => this.apply());

        if (this.toggleButton) {
            this.toggleButton.addEventListener('target-enhancement.close', () => this.onClose());
        }
    }

}
