import {createReducer, on} from "@ngrx/store";
import {Account, List} from "projects/mastodon-api/src/public-api";
import {FiltersActions, ListActions, MastodonApiActions} from "./actions";

export interface Filters {
    username: string;
    freeText: ReadonlyArray<string>;
    lists: ReadonlyArray<string>;
    unlisted: boolean;
}

export interface ApplicationState {
    listsLoading: boolean;
    listAccountsLoading: boolean;
    followingsLoading: boolean;
    lists: ReadonlyArray<List>;
    listsAccounts: { [listId: string]: string[] };
    followings: ReadonlyArray<Account>;
    filters: Filters;
}

export const initialState: ApplicationState = {
    listsLoading: false,
    listAccountsLoading: false,
    followingsLoading: false,
    lists: [],
    listsAccounts: {},
    followings: [],
    filters: {
        username: '',
        freeText: [],
        lists: [],
        unlisted: false,
    }
}

export const applicationStateReducers = createReducer(
        initialState,
        on(MastodonApiActions.loadLists, _state => {
            return {..._state, listsLoading: true};
        }),
        on(MastodonApiActions.listsLoaded, (_state, {lists}) => {
            return {..._state, listsLoading: false, listAccountsLoading: true, lists: lists,};
        }),
        on(MastodonApiActions.accountIdsForListsLoaded, (_state, {mappings}) => {
            return {..._state, listAccountsLoading: false, listsAccounts: mappings};
        }),
        on(MastodonApiActions.followingsLoaded, (_state, {followings}) => {
            return {..._state, followingsLoading: false, followings};
        }),
        on(MastodonApiActions.followingsLoadedError, (_state, {error}) => {
            console.error(error);
            return {..._state};
        }),
        on(ListActions.addAccountToList, (_state, {accountId, listId}) => {
            const existingAccountIds = _state.listsAccounts[listId] || [];
            const newAccountIds = [...existingAccountIds, accountId];
            const newMap: { [listId: string]: string[] } = {..._state.listsAccounts, [listId]: newAccountIds};
            return <ApplicationState>{
                ..._state,
                listsAccounts: newMap,
            }
        }),
        on(ListActions.removeAccountFromList, (_state, {accountId, listId}) => {
            const existingAccountIds = _state.listsAccounts[listId] || [];
            const newAccountIds = existingAccountIds.filter(id => id !== accountId);
            const newMap: { [listId: string]: string[] } = {..._state.listsAccounts, [listId]: newAccountIds};
            return <ApplicationState>{
                ..._state,
                listsAccounts: newMap,
            }
        }),
        on(FiltersActions.setUsername, (_state, {username}) => {
            return {..._state, filters: {..._state.filters, username}};
        }),
        on(FiltersActions.setFreeText, (_state, {freeText}) => {
            return {..._state, filters: {..._state.filters, freeText}};
        }),
        on(FiltersActions.setLists, (_state, {lists}) => {
            return {..._state, filters: {..._state.filters, lists}};
        }),
        on(FiltersActions.setUnlisted, (_state, {unlisted}) => {
            let newState = {..._state, filters: {..._state.filters, unlisted}};
            if (unlisted) {
                newState = {...newState, filters: {...newState.filters, lists: []}};
            }
            return newState;
        }),
        on(FiltersActions.clearFilters, _state => {
            return {..._state, filters: initialState.filters};
        }),
    )
;
