// See [Common MIME types](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types)
const FileTypes = [
    {
        description: 'Images',
        accept: {
            'image/*': [
                '.avif',
                '.gif',
                // '.ico',
                '.jpeg',
                '.jpg',
                '.png',
                '.tif',
                '.tiff',
                // '.svg',
                '.webp',
            ],
        },
    },
    {
        description: 'Videos',
        accept: {
            'video/*': [
                '.avi',
                '.mp4',
                '.mpeg',
                '.ogg',
                // '.ts',
                '.webm',
                '.3gp',
                '.3g2',
            ],
        },
    },
    {
        description: 'Audios',
        accept: {
            'audio/*': [
                '.aac',
                '.mid',
                '.midi',
                '.mp3',
                '.oga',
                '.opus',
                '.wav',
                '.weba',
                '.3gp',
                '.3g2',
            ],
        },
    },
    {
        description: 'Markdown',
        accept: {
            'text/markdown': ['.md', '.markdown'],
        },
    },
    {
        description: 'Html',
        accept: {
            'text/html': ['.html', '.htm'],
        },
    },
    {
        description: 'Zip',
        accept: {
            'application/zip': ['.zip'],
        },
    },
];
export async function openFileOrFiles({ acceptType = 'Any', multiple = false, } = {}) {
    // Feature detection. The API needs to be supported
    // and the app not run in an iframe.
    const supportsFileSystemAccess = 'showOpenFilePicker' in window &&
        (() => {
            try {
                return window.self === window.top;
            }
            catch {
                return false;
            }
        })();
    // If the File System Access API is supported…
    if (supportsFileSystemAccess && window.showOpenFilePicker) {
        try {
            const fileType = FileTypes.find(i => i.description === acceptType);
            if (acceptType !== 'Any' && !fileType)
                throw new Error(`Unexpected acceptType "${acceptType}"`);
            const pickerOpts = {
                types: fileType ? [fileType] : undefined,
                multiple,
            };
            // Show the file picker, optionally allowing multiple files.
            const handles = await window.showOpenFilePicker(pickerOpts);
            // Only one file is requested.
            if (!multiple) {
                // Add the `FileSystemFileHandle` as `.handle`.
                const file = await handles[0].getFile();
                // Add the `FileSystemFileHandle` as `.handle`.
                // file.handle = handles[0];
                return file;
            }
            else {
                const files = await Promise.all(handles.map(async (handle) => {
                    const file = await handle.getFile();
                    // Add the `FileSystemFileHandle` as `.handle`.
                    // file.handle = handles[0];
                    return file;
                }));
                return files;
            }
        }
        catch (err) {
            if (!(err instanceof Error))
                throw err;
            // Fail silently if the user has simply canceled the dialog.
            if (err.name !== 'AbortError')
                throw err;
            return null;
        }
    }
    // Fallback if the File System Access API is not supported.
    return new Promise(resolve => {
        // Append a new `<input type="file" multiple? />` and hide it.
        const input = document.createElement('input');
        input.classList.add('affine-upload-input', 'blockeditor-overlay');
        input.style.display = 'none';
        input.type = 'file';
        if (multiple) {
            input.multiple = true;
        }
        if (acceptType !== 'Any') {
            // For example, `accept="image/*"` or `accept="video/*,audio/*"`.
            input.accept = Object.keys(FileTypes.find(i => i.description === acceptType)?.accept ?? '').join(',');
        }
        document.body.append(input);
        // The `change` event fires when the user interacts with the dialog.
        input.addEventListener('change', () => {
            // Remove the `<input type="file" multiple? />` again from the DOM.
            input.remove();
            // If no files were selected, return.
            if (!input.files) {
                resolve(null);
                return;
            }
            // Return all files or just one file.
            if (multiple) {
                resolve(Array.from(input.files));
                return;
            }
            resolve(input.files[0]);
        });
        // Show the picker.
        if ('showPicker' in HTMLInputElement.prototype) {
            input.showPicker();
        }
        else {
            input.click();
        }
    });
}
export async function getImageFilesFromLocal() {
    const imageFiles = await openFileOrFiles({
        acceptType: 'Images',
        multiple: true,
    });
    if (!imageFiles)
        return [];
    return imageFiles;
}
export async function uploadImageFromLocal(storage) {
    const imageFiles = await openFileOrFiles({
        acceptType: 'Images',
        multiple: true,
    });
    if (!imageFiles)
        return [];
    return loadImages(imageFiles, storage);
}
export async function loadImages(images, storage) {
    const res = [];
    for (let i = 0; i < images.length; i++) {
        const file = images[i];
        const sourceId = await storage.set(file);
        res.push({ file, sourceId });
    }
    const { saveAttachmentData } = withTempBlobData();
    res.forEach(({ file, sourceId }) => {
        saveAttachmentData(sourceId, { name: file.name });
    });
    return res;
}
export function downloadBlob(blob, name) {
    const dataURL = URL.createObjectURL(blob);
    const tmpLink = document.createElement('a');
    const event = new MouseEvent('click');
    tmpLink.download = name;
    tmpLink.href = dataURL;
    tmpLink.dispatchEvent(event);
    tmpLink.remove();
    URL.revokeObjectURL(dataURL);
}
// Use lru strategy is a better choice, but it's just a temporary solution.
const MAX_TEMP_DATA_SIZE = 100;
/**
 * TODO @Saul-Mirone use some other way to store the temp data
 *
 * @deprecated Waiting for migration
 */
const tempAttachmentMap = new Map();
const tempImageMap = new Map();
/**
 * Because the image block and attachment block have different props.
 * We need to save some data temporarily when converting between them to ensure no data is lost.
 *
 * For example, before converting from an image block to an attachment block,
 * we need to save the image's width and height.
 *
 * Similarly, when converting from an attachment block to an image block,
 * we need to save the attachment's name.
 *
 * See also https://github.com/toeverything/blockeditor/pull/4583#pullrequestreview-1610662677
 *
 * @internal
 */
export function withTempBlobData() {
    const saveAttachmentData = (sourceId, data) => {
        if (tempAttachmentMap.size > MAX_TEMP_DATA_SIZE) {
            console.warn('Clear the temp attachment data. It may cause filename loss when converting between image and attachment.');
            tempAttachmentMap.clear();
        }
        tempAttachmentMap.set(sourceId, data);
    };
    const getAttachmentData = (blockId) => {
        const data = tempAttachmentMap.get(blockId);
        tempAttachmentMap.delete(blockId);
        return data;
    };
    const saveImageData = (sourceId, data) => {
        if (tempImageMap.size > MAX_TEMP_DATA_SIZE) {
            console.warn('Clear temp image data. It may cause image width and height loss when converting between image and attachment.');
            tempImageMap.clear();
        }
        tempImageMap.set(sourceId, data);
    };
    const getImageData = (blockId) => {
        const data = tempImageMap.get(blockId);
        tempImageMap.delete(blockId);
        return data;
    };
    return {
        saveAttachmentData,
        getAttachmentData,
        saveImageData,
        getImageData,
    };
}
//# sourceMappingURL=filesys.js.map