import { createSlice, Dictionary, EntityId } from '@reduxjs/toolkit';
import {
    completeDownload,
    downloadAdapter,
    failDownload,
    initializeDownload,
    progressDownload,
    queueTrackForDownload,
    removeDownloadedTrack
} from './actions';
import { DownloadEntity } from './types';

interface State {
    entities: Dictionary<DownloadEntity>;
    ids: EntityId[];
    queued: EntityId[];
}

export const initialState: State = {
    entities: {},
    ids: [],
    queued: [],
};

const downloads = createSlice({
    name: 'downloads',
    initialState,
    reducers: {},
    extraReducers: builder => {
        builder.addCase(initializeDownload, (state, action) => {
            downloadAdapter.upsertOne(state, {
                ...action.payload,
                progress: 0,
                isFailed: false,
                isComplete: false,
            });
        });
        builder.addCase(progressDownload, (state, action) => {
            downloadAdapter.updateOne(state, {
                id: action.payload.id,
                changes: action.payload
            });
        });
        builder.addCase(completeDownload, (state, action) => {
            // Update the item to be completed
            downloadAdapter.updateOne(state, {
                id: action.payload.id,
                changes: {
                    ...action.payload,
                    isFailed: false,
                    isComplete: true,
                }
            });

            // Remove the item from the queue
            const newSet = new Set(state.queued);
            newSet.delete(action.payload.id);
            state.queued = Array.from(newSet);
        });
        builder.addCase(failDownload, (state, action) => {
            downloadAdapter.updateOne(state, {
                id: action.payload.id,
                changes: {
                    isComplete: false,
                    isFailed: true,
                    progress: 0,
                }
            });
        });
        builder.addCase(removeDownloadedTrack.fulfilled, (state, action) => {
            // Remove the download if it exists
            downloadAdapter.removeOne(state, action.meta.arg);

            // Remove the item from the queue if it is in there
            const newSet = new Set(state.queued);
            newSet.delete(action.meta.arg);
            state.queued = Array.from(newSet);
        });
        builder.addCase(queueTrackForDownload, (state, action) => {
            const newSet = new Set(state.queued).add(action.payload);
            state.queued = Array.from(newSet);
        });
    },
});

export default downloads;