import { createAction, createAsyncThunk, createEntityAdapter, EntityId } from '@reduxjs/toolkit';
import { AppState } from 'store';
import { generateTrackUrl } from 'utility/JellyfinApi';
import { downloadFile, unlink, DocumentDirectoryPath } from 'react-native-fs';
import { DownloadEntity } from './types';

export const downloadAdapter = createEntityAdapter<DownloadEntity>({
    selectId: (entity) => entity.id,
});

export const queueTrackForDownload = createAction<EntityId>('download/queue');
export const initializeDownload = createAction<{ id: EntityId, size?: number, jobId?: number }>('download/initialize');
export const progressDownload = createAction<{ id: EntityId, progress: number, jobId?: number }>('download/progress');
export const completeDownload = createAction<{ id: EntityId, location: string, size?: number }>('download/complete');
export const failDownload = createAction<{ id: EntityId }>('download/fail');

export const downloadTrack = createAsyncThunk(
    '/downloads/track',
    async (id: EntityId, { dispatch, getState }) => {
        // Get the credentials from the store
        const { settings: { jellyfin: credentials } } = (getState() as AppState);

        // Generate the URL we can use to download the file
        const url = generateTrackUrl(id as string, credentials);
        const location = `${DocumentDirectoryPath}/${id}.mp3`;

        // Actually kick off the download
        const { promise } = await downloadFile({
            fromUrl: url,
            progressInterval: 250,
            background: true,
            begin: ({ jobId, contentLength }) => {
                // Dispatch the initialization
                dispatch(initializeDownload({ id, jobId, size: contentLength }));
            },
            progress: (result) => {
                // Dispatch a progress update
                dispatch(progressDownload({ id, progress: result.bytesWritten / result.contentLength }));
            },
            toFile: location,
        });

        // Await job completion
        const result = await promise;
        dispatch(completeDownload({ id, location, size: result.bytesWritten }));
    },
);

export const removeDownloadedTrack = createAsyncThunk(
    '/downloads/remove/track',
    async(id: EntityId) => {
        return unlink(`${DocumentDirectoryPath}/${id}.mp3`);
    }
);