#include utility.js
#include watcher.js

const MsgMessagesList = function(list) {
    if(!(list instanceof Element))
        throw 'list must be an element';

    const watchers = new MszWatchers;
    watchers.define(['select']);

    let selectedCount = 0;

    const items = Array.from(list.querySelectorAll('.js-messages-entry')).map(elem => {
        const item = new MsgMessagesEntry(elem);
        item.onSelectedChange((state, initial) => {
            if(state)
                ++selectedCount;
            else if(!initial)
                --selectedCount;

            if(!initial)
                watchers.call('select', selectedCount, items.length);
        });
        return item;
    });

    const recountSelected = () => {
        selectedCount = 0;

        for(const item of items)
            if(item.getSelected())
                ++selectedCount;
    };

    const onSelectedChange = handler => {
        watchers.watch('select', handler, selectedCount, items.length);
    };

    onSelectedChange(selectedCount => {
        const state = selectedCount > 0;
        for(const item of items)
            item.setClickIsSelect(state);
    });

    return {
        getItems: () => items,
        getItemsCount: () => items.length,
        getSelectedItems: () => {
            const selected = [];

            for(const item of items)
                if(item.getSelected())
                    selected.push(item);

            return selected;
        },
        removeItem: item => {
            $ari(items, item);
            $r(item.getElement());
            recountSelected();
            watchers.call('select', selectedCount, items.length);
        },
        getAllSelected: () => {
            if(items.length < 1)
                return false;

            for(const item of items)
                if(!item.getSelected())
                    return false;

            return true;
        },
        setAllSelected: state => {
            for(const item of items)
                item.setSelected(state);
            selectedCount = state ? items.length : 0;
            watchers.call('select', selectedCount, items.length);
        },
        onSelectedChange: onSelectedChange,
    };
};

const MsgMessagesEntry = function(entry) {
    if(!(entry instanceof Element))
        throw 'entry must be an element';

    const msgId = entry.dataset.msgId;

    const unreadElem = entry.querySelector('.js-messages-entry-unread');
    const isRead = () => entry.dataset.msgRead === 'read';
    const setRead = state => {
        if(state) {
            entry.dataset.msgRead = 'read';
            unreadElem.hidden = true;
        } else {
            entry.dataset.msgRead = 'unread';
            unreadElem.hidden = false;
        }
    };

    const isSent = () => entry.dataset.msgSent === 'sent';
    const setSent = state => {
        entry.dataset.msgRead = state ? 'sent' : 'draft';
    };

    const checkbox = entry.querySelector('.js-entry-checkbox');
    const getSelected = () => checkbox.checked;
    const setSelected = state => checkbox.checked = state;
    const toggleSelected = () => checkbox.checked = !checkbox.checked;

    let clickIsSelect = false;

    const watchers = new MszWatchers;
    watchers.define(['select']);

    checkbox.addEventListener('click', ev => ev.stopPropagation());
    checkbox.addEventListener('keydown', ev => ev.stopPropagation());

    checkbox.addEventListener('change', () => {
        watchers.call('select', getSelected());
    });

    const navigateToMessage = () => {
        const url = entry.dataset.msgUrl;
        if(url !== undefined && url.startsWith('/') && !url.startsWith('//'))
            location.assign(url);
    };

    entry.addEventListener('keydown', ev => {
        if(ev.key === 'Enter' || ev.key === 'NumpadEnter') {
            ev.preventDefault();
            entry.click();
        }
    });

    entry.addEventListener('click', ev => {
        ev.preventDefault();

        if(clickIsSelect)
            checkbox.click();
        else
            navigateToMessage();
    });

    entry.addEventListener('dblclick', ev => {
        ev.preventDefault();

        if(clickIsSelect)
            navigateToMessage();
    });

    return {
        getId: () => msgId,
        getElement: () => entry,
        isRead: isRead,
        setRead: setRead,
        isSent: isSent,
        setSent: setSent,
        getSelected: getSelected,
        setSelected: setSelected,
        toggleSelected: toggleSelected,
        setClickIsSelect: state => clickIsSelect = state,
        onSelectedChange: handler => {
            watchers.watch('select', handler, getSelected());
        },
    };
};
