import Immutable from 'immutable';
import { ReduceStore } from 'flux/utils';
import { ActionTypes } from 'constants/Common';
import Notifications from 'constants/Notifications';
import dispatcher from 'dispatcher';

function toKey(value) {
    if (value === undefined || value === null) {
        return String(Math.random());
    }

    return value;
}

class NotificationStore extends ReduceStore {
    getInitialState() {
        this._background = new Immutable.Map();

        return new Immutable.OrderedMap();
    }

    reduce(state, action) {
        const { data, type } = action;

        switch (type) {
            case ActionTypes.NOTIFY:
                return this._receiveNotification(state, data);

            case ActionTypes.SEND_BACKGROUND_NOTIFICATION:
                return this._receiveBackgroundNotification(state, data);

            case ActionTypes.CANCEL_BACKGROUND_NOTIFICATION:
                return this._cancelBackgroundNotification(state, data);

            case ActionTypes.REMOVE_NOTIFICATION:
                return state.remove(data.key);
        }

        return state;
    }

    _receiveNotification(state, data = {}) {
        data.key = toKey(data.key);

        if (!data.message) {
            return state;
        }

        setTimeout(() => {
            // проверяем наличие перед вызовом события
            // нотификация могла быть закрыта вручную раньше
            if (this._state.has(data.key)) {
                dispatcher.dispatch(ActionTypes.REMOVE_NOTIFICATION, { key: data.key });
                if (data.options && data.options.onClose) {
                    data.options.onClose();
                }
            }
        }, Notifications.NOTIFICATION_TIMEOUT);

        return state.set(data.key, data);
    }

    _receiveBackgroundNotification(state, data = {}) {
        data.displayTimeout = setTimeout(() => {
            dispatcher.dispatch(ActionTypes.NOTIFY, data);
        }, Notifications.BACKGROUND_NOTIFICATION_TIMEOUT);

        this._background = this._background.set(data.key, data.displayTimeout);

        return state;
    }

    _cancelBackgroundNotification(state, data = {}) {
        const backgroundTimeout = this._background.get(data.key);

        if (backgroundTimeout) {
            clearTimeout(backgroundTimeout);
            this._background = this._background.remove(data.key);
        }

        return state;
    }

    getAll() {
        return this._state.toArray();
    }
}

export default window.ya.connect.NotificationStore = new NotificationStore(dispatcher);
