import {createReducer, on} from "@ngrx/store";
import {List} from "projects/mastodon-api/src/public-api";
import {fromApplication, fromFilters, fromListViewPage, fromMastodonApi, fromMatrixViewPage, fromTableViewPage} from "../actions";
import {ApplicationState, initialState} from "../application-state";

export const applicationStateReducer = createReducer(
    initialState,
    on(fromApplication.loadLists, _state => {
        return {..._state, listsLoading: true};
    }),
    on(fromMastodonApi.listsLoadedSuccess, (_state, {lists}) => {
        return {..._state, listsLoading: false, listAccountsLoading: true, lists: lists,};
    }),
    on(fromMastodonApi.accountIdsForListsLoadedSuccess, (_state, {mappings}) => {
        return {..._state, listAccountsLoading: false, listsAccounts: mappings};
    }),
    on(fromMastodonApi.followingsLoadedSuccess, (_state, {followings}) => {
        return {..._state, followingsLoading: false, followings};
    }),
    on(fromMastodonApi.followingsLoadedError, (_state, {error}) => {
        console.error(error);
        return {..._state};
    }),
    on(
        fromListViewPage.addAccountToList,
        fromMatrixViewPage.addAccountToList,
        fromTableViewPage.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(
        fromListViewPage.removeAccountFromList,
        fromMatrixViewPage.removeAccountFromList,
        fromTableViewPage.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(
        fromFilters.setUsername,
        (_state, {username}) => {
            return {..._state, filters: {..._state.filters, username}};
        }),
    on(
        fromFilters.setFreeText,
        (_state, {freeText}) => {
            return {..._state, filters: {..._state.filters, freeText}};
        }),
    on(
        fromFilters.setLists,
        (_state, {lists}) => {
            return {..._state, filters: {..._state.filters, lists}};
        }),
    on(
        fromFilters.setUnlisted,
        (_state, {unlisted}) => {
            let newState = {..._state, filters: {..._state.filters, unlisted}};
            if (unlisted) {
                newState = {...newState, filters: {...newState.filters, lists: []}};
            }
            return newState;
        }),
    on(
        fromFilters.clearFilters,
        _state => {
            return {..._state, filters: initialState.filters};
        }),
    on(fromMastodonApi.createListSuccess, (_state, {listId, title}) => {
        const newListsArray = [..._state.lists, {id: listId, title: title, repliesPolicy: 'list', accounts: []}].sort((a, b) => a.title.localeCompare(b.title));
        return {
            ..._state,
            listsAccounts: {..._state.listsAccounts, [listId]: []},
            lists: newListsArray,
        };
    }),
    on(fromMastodonApi.updateListSuccess, (_state, {listId, newTitle}) => {
        const listToUpdate = _state.lists.find(list => list.id === listId) as List;
        const newListsArray = [..._state.lists.filter(list => list.id !== listId), {...listToUpdate, title: newTitle}].sort((a, b) => a.title.localeCompare(b.title));
        return {
            ..._state,
            lists: newListsArray,
        };
    }),
);
