import _ from 'lodash';
import Immutable from 'immutable';
import { ReduceStore } from 'flux/utils';
import { ActionTypes } from 'constants/Common';
import dispatcher from 'dispatcher';
import Group from 'records/Group';
import UserStore from 'stores/Users';

function compareByName(a, b) {
    const aName = a.toSortableString();
    const bName = b.toSortableString();

    if (aName === bName) {
        return 0;
    }

    return aName > bName ? 1 : -1;
}

class GroupStore extends ReduceStore {
    getInitialState() {
        return Immutable.fromJS({
            index: {}, lists: {}, flat_lists: {},
        });
    }

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

        switch (type) {
            case ActionTypes.RECEIVE_MIXED_DATA:
                return this._receiveRawData(state, data);
            case ActionTypes.RECEIVE_GROUP:
                return state.setIn(['index', data.id], data);
            case ActionTypes.DISCARD_GROUP:
                return state.removeIn(['index', data.id]);
            default:
                return state;
        }
    }

    /**
     * Возвращает команду по id
     * @method  get
     * @param   {String} id
     * @returns {?Group}
     */
    get(id) {
        return this._state.getIn(['index', id]);
    }

    /**
     * Возвращает команду с админами организации
     * @returns {?Group}
     */
    getAdminGroup() {
        const groups = this._state.get('index');
        let adminGroup = groups.find(group => group.type === 'organization_admin');

        if (!adminGroup) {
            adminGroup = Group.create({
                id: '2',
                type: 'organization_admin',
                members: UserStore.getAdmins().map(user => ({ id: user.getId(), type: 'user' })),
            });
            this._state = this._state.setIn(['index', 'org_admins'], adminGroup);
        }

        return adminGroup;
    }

    getList(type) {
        const index = this._state.get('index');
        let list = (index ? index.toArray() : null) || [];
        let filterList;

        // в списках отображаем только generic команды
        list = list.filter(item => item.get('type') === 'generic');

        if (type) {
            filterList = this._state.getIn(['lists', type]);
        }

        if (filterList) {
            filterList = filterList.toArray();
            list = list.filter(item => filterList.indexOf(item.getId()) !== -1);
        }

        return list.sort(compareByName);
    }

    getFlatMemberList(id) {
        const list = this._state.getIn(['flat_lists', id]);

        if (!list) {
            return [];
        }

        return list.toArray().map(userId => UserStore.get(userId));
    }

    /**
     * Возвращает отсортированный список групп по списоку их id-ов
     * @param {Array} ids
     * @returns {Array}
     */
    getOrderedList(ids) {
        return _.sortBy(
            ids ? ids.map(id => this.get(id)) : [],
            group => group ? group.toSortableString() : null
        ).filter(Boolean);
    }

    getName(id) {
        const item = this.get(id);

        return item ? item.getName() : id;
    }

    hasAllData(id) {
        const item = this.get(id);

        return item ? item.hasAllData() : false;
    }

    _receiveRawData(state, data) {
        let nextState = state;

        if (data.groups) {
            const nextIndex = new Immutable.Map(data.groups)
                .map(item => Group.create(item));

            nextState = nextState.mergeIn(['index'], nextIndex);
        }

        // находим упорядоченный список команд среди data.lists
        // в нем только команды, соответствующие заданному подразделу
        const order = (_.find(data.lists, { type: 'groups' }) || {}).order;

        if (data.tag === 'member' || data.tag === 'admin') {
            const nextList = new Immutable.List(order);

            nextState = nextState.mergeIn(['lists'], new Immutable.Map([
                [data.tag, nextList],
            ]));
        }

        const list = _.find(data.lists, { type: 'users' });

        if (data.tag === 'flat_group') {
            const id = _.get(list, 'query.recursive_group_id');

            if (id && list.order) {
                const nextList = new Immutable.List(list.order);

                nextState = nextState.mergeIn(['flat_lists'], new Immutable.Map([
                    [id, nextList],
                ]));
            }
        }

        return nextState;
    }
}

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