import { attributeSelector } from '../common/selector-utilities';
import { ResultsListController } from '../common/results-list-controller.class';
import { dateToShortIsoString } from '../common/date-formatting';
import { fireEvent } from '@nimius/event-utility';

const ATTRIBUTE = Object.freeze({
    DATE_PICKER: 'data-toubiz-date-picker',
    DATE_PICKER_BUTTON: 'data-toubiz-date-picker-button',
    DATE_LINK: 'data-toubiz-events-date',
    DATE_RESET: 'data-toubiz-events-date-reset-button',
    FROM_DATE: 'data-toubiz-events-from-date',
    TO_DATE: 'data-toubiz-events-to-date',
    ACTIVE_CLASSES: 'data-toubiz-events-date.add-class-if-active',
});

export class EventsResultsListController extends ResultsListController {

    /** @protected */
    onInitialize () {
        this.initializeEventSpecificBehaviour();
    }

    /** @protected */
    onReinitialize () {
        this.initializeEventSpecificBehaviour();
    }

    /** @private */
    initializeEventSpecificBehaviour () {
        this.updateDateFields();
        this.initializeDateLinks();
        this.initializeDatePicker();
        this.initializeDateResetButton();
    }

    /** @private */
    updateDateFields () {
        this.fromDate = this.select(attributeSelector(ATTRIBUTE.FROM_DATE));
        this.toDate = this.select(attributeSelector(ATTRIBUTE.TO_DATE));
    }

    /** @private */
    initializeDateLinks () {
        const links = this.select(attributeSelector(ATTRIBUTE.DATE_LINK), true);
        for (const link of links) {
            link.addEventListener('click', event => {
                event.preventDefault();
                this.updateDates(link.getAttribute(ATTRIBUTE.DATE_LINK), link.getAttribute(ATTRIBUTE.DATE_LINK), link);
            });
        }
    }

    /** @private */
    initializeDatePicker () {
        const picker = this.select(attributeSelector(ATTRIBUTE.DATE_PICKER));
        if (!picker) {
            return;
        }

        const pickerButton = this.select(attributeSelector(ATTRIBUTE.DATE_PICKER_BUTTON));
        picker.addEventListener(
            'toubiz-date-picker.change',
            event => this.updateDates(event.detail.range.start, event.detail.range.end, pickerButton),
        );
    }

    /** @private */
    initializeDateResetButton () {
        const button = this.select(attributeSelector(ATTRIBUTE.DATE_RESET));
        if (!button) {
            return;
        }

        // @todo
        // Somehow the event listener is registered twice and the number of form reloads would duplicate on every click.
        // This prevents that from happening until the actual bug is fixed.
        if (button.getAttribute('initialized') === '1') {
            return;
        }

        button.addEventListener('click', event => {
            event.preventDefault();
            this.fromDate.value = '';
            this.toDate.value = '';
            this.formReload.reload();
            this.toggleSelection(button, false);
        });

        button.setAttribute('initialized', '1');
    }

    /**
     * @private
     * @param {Date|string} fromDate
     * @param {Date|string} toDate
     * @param {HTMLElement} element
     */
    updateDates (fromDate, toDate, element) {
        const fromBefore = this.fromDate.value;
        const toBefore = this.toDate.value;

        const from = (fromDate instanceof Date) ? fromDate : this.parseDateString(fromDate);
        const to = (toDate instanceof Date) ? toDate : this.parseDateString(toDate);
        this.fromDate.value = dateToShortIsoString(from);
        this.toDate.value = dateToShortIsoString(to);

        if (fromBefore !== this.fromDate.value || toBefore !== this.toDate.value) {
            const picker = this.select(attributeSelector(ATTRIBUTE.DATE_PICKER));
            fireEvent(picker, 'toubiz-date-picker.set', { start: from, end: to });
            this.formReload.reload();
            this.toggleSelection(element);
        }
    }

    /**
     * @private
     * @param {string} string
     * @returns {Date}
     */
    parseDateString (string) {
        const date = new Date();
        switch (string) {
            case 'today':
                return date;
            case 'tomorrow':
                date.setDate(date.getDate() + 1);
                return date;
            default:
                return new Date(string);
        }
    }

    toggleSelection (element, state = true) {
        const links = this.select(attributeSelector(ATTRIBUTE.DATE_LINK), true);
        const pickerButton = this.select(attributeSelector(ATTRIBUTE.DATE_PICKER_BUTTON));
        const reset = this.select(attributeSelector(ATTRIBUTE.DATE_RESET));

        let classes = [];
        if (element.hasAttribute(ATTRIBUTE.ACTIVE_CLASSES)) {
            classes = element.getAttribute(ATTRIBUTE.ACTIVE_CLASSES).split(' ');
        }

        for (const link of links) {
            link.classList.remove(...classes);
        }

        element.classList.remove(...classes);
        pickerButton.classList.remove(...classes);
        reset.classList.remove('hidden');
        reset.classList.add('hidden');

        if (state === true) {
            element.classList.add(...classes);
            pickerButton.classList.add(...classes);
            reset.classList.remove('hidden');
        }
    }
}
