import { expect } from 'chai';
import { ItemFilter } from './item-filter';

describe('item-filter', () => {

    /**
     * @param {HTMLInputElement} input
     * @param {string} value
     */
    function type(input, value) {
        input.value = value;
        const event = document.createEvent('CustomEvent');
        event.initCustomEvent('input', true, true, {});
        input.dispatchEvent(event);
    }

    /**
     * @param {string[]} items
     * @param {object} attributes
     * @returns {object}
     */
    function initialize(items, attributes = {}) {
        const itemMarkup = items
            .map(item => `<li id="item-${item}">${item}</li>`)
            .join('\n');

        const container = document.createElement('div');
        Object.keys(attributes)
            .forEach(key => container.setAttribute(key, attributes[key]));
        container.innerHTML = `
            <input style="display: none" data-item-filter.query id="list-query">
            
            <ul data-item-filter.item-container="list" id="list-container">
                ${itemMarkup}
            </ul>
            
            <button style="display: none;" data-item-filter.show-more id="show-more-list">show more</button>
            <button style="display: none;" data-item-filter.show-less id="show-less-list">show less</button>
           
        `;

        const itemFilter = new ItemFilter(container);
        const elements = {
            listQuery: container.querySelector('#list-query'),
            listContainer: container.querySelector('#list-container'),
            showMoreList: container.querySelector('#show-more-list'),
            showLessList: container.querySelector('#show-less-list'),
        };

        items.forEach(item => elements[item] = container.querySelector(`#item-${item}`));
        return { itemFilter, container, ...elements };
    }

    it('should filter the list when typing', () => {
        const { foo, bar, baz, listQuery } = initialize([ 'foo', 'bar', 'baz' ]);
        expect(foo.style.display).to.not.equal('none');
        expect(bar.style.display).to.not.equal('none');
        expect(baz.style.display).to.not.equal('none');
        type(listQuery, 'ba');
        expect(foo.style.display).to.equal('none');
        expect(bar.style.display).to.not.equal('none');
        expect(baz.style.display).to.not.equal('none');
    });

    it('should ignore casing when searching', () => {
        const { foo, bar, baz, listQuery } = initialize([ 'foo', 'bar', 'baz' ]);
        type(listQuery, 'FoO');
        expect(foo.style.display).to.not.equal('none');
        expect(bar.style.display).to.equal('none');
        expect(baz.style.display).to.equal('none');
    });

    it('should show more items when clicking on a show more button', () => {
        const { foo, bar, baz, bazzer, buzzer, showMoreList, showLessList } = initialize(
            [ 'foo', 'bar', 'baz', 'bazzer', 'buzzer' ],
            { 'data-item-filter.list.limit': 3 }
        );
        expect(foo.style.display).to.not.equal('none', 'only 3 items should be visible in the beginning');
        expect(bar.style.display).to.not.equal('none', 'only 3 items should be visible in the beginning');
        expect(baz.style.display).to.not.equal('none', 'only 3 items should be visible in the beginning');
        expect(bazzer.style.display).to.equal('none', 'only 3 items should be visible in the beginning');
        expect(buzzer.style.display).to.equal('none', 'only 3 items should be visible in the beginning');

        showMoreList.click();

        expect(foo.style.display).to.not.equal(
            'none',
            'all items should be visible after clicking the show more button'
        );
        expect(bar.style.display).to.not.equal(
            'none',
            'all items should be visible after clicking the show more button'
        );
        expect(baz.style.display).to.not.equal(
            'none',
            'all items should be visible after clicking the show more button'
        );
        expect(bazzer.style.display).to.not.equal(
            'none',
            'all items should be visible after clicking the show more button'
        );
        expect(buzzer.style.display).to.not.equal(
            'none',
            'all items should be visible after clicking the show more button'
        );

        showLessList.click();

        expect(foo.style.display).to.not.equal(
            'none',
            'only 3 items should be visible after clicking the show less button'
        );
        expect(bar.style.display).to.not.equal(
            'none',
            'only 3 items should be visible after clicking the show less button'
        );
        expect(baz.style.display).to.not.equal(
            'none',
            'only 3 items should be visible after clicking the show less button'
        );
        expect(bazzer.style.display).to.equal(
            'none',
            'only 3 items should be visible after clicking the show less button'
        );
        expect(buzzer.style.display).to.equal(
            'none',
            'only 3 items should be visible after clicking the show less button'
        );
    });

    it('should not display more button if all items are currently being displayed', () => {
        const { showMoreList, showLessList } = initialize(
            [ 'foo', 'bar' ],
            { 'data-item-filter.list.limit': 5 }
        );

        expect(showMoreList.style.display).to.equal('none');
        expect(showLessList.style.display).to.equal('none');
    });

});
