const MszEEPROM = function(appId) {
    if(typeof appId !== 'string')
        throw 'appId must be a string';

    return {
        create: fileInput => {
            if(!(fileInput instanceof File))
                throw 'fileInput must be an instance of window.File';

            let userAborted = false;
            let abortHandler;
            let progressHandler;

            const reportProgress = ev => {
                if(progressHandler !== undefined)
                    progressHandler({
                        loaded: ev.loaded,
                        total: ev.total,
                        progress: ev.total <= 0 ? 0 : ev.loaded / ev.total,
                    });
            };

            return {
                abort: () => {
                    userAborted = true;
                    if(typeof abortHandler === 'function')
                        abortHandler();
                },
                onProgress: handler => {
                    if(typeof handler !== 'function')
                        throw 'handler must be a function';
                    progressHandler = handler;
                },
                start: async () => {
                    if(userAborted)
                        throw 'File upload was cancelled by the user, it cannot be restarted.';

                    try {
                        const formData = new FormData;
                        formData.append('src', appId);
                        formData.append('file', fileInput);

                        const { status, body } = await $xhr.post('/uploads', {
                            type: 'json',
                            authed: true,
                            upload: reportProgress,
                            abort: handler => abortHandler = handler,
                        }, formData);
                        if(body === null)
                            throw "The upload server didn't return the metadata for some reason.";

                        if(status !== 201)
                            throw body.english ?? body.error ?? `Upload failed with status code ${status}`;

                        body.isImage = () => body.type.startsWith('image/');
                        body.isVideo = () => body.type.startsWith('video/');
                        body.isAudio = () => body.type.startsWith('audio/');
                        body.isMedia = () => body.isImage() || body.isAudio() || body.isVideo();

                        return Object.freeze(body);
                    } catch(ex) {
                        if(userAborted)
                            throw '';

                        console.error(ex);
                        throw ex;
                    }
                },
            };
        },

        delete: async fileInfo => {
            if(typeof fileInfo !== 'object')
                throw 'fileInfo must be an object';
            if(typeof fileInfo.urlf !== 'string')
                throw 'fileInfo.urlf must be a string';

            const { status, body } = await $xhr.delete(fileInfo.urlf, {
                type: 'json',
                authed: true,
            });

            if(status !== 204) {
                if(body === null)
                    throw `Delete failed with status code ${status}`;

                throw body.english ?? body.error ?? `Delete failed with status code ${status}`;
            }
        },
    };
};