import {toRequestUrl, get, upload as uploadFile} from './index.ts';
import * as StringUtil from '../util/string.ts';

export const PROTOCOL = 'fss://';

export type UploadLimit = {
    extensions: string[];
    extensionsRejected?: boolean;
    capacityBytes?: number;
};

export type FssReadUrl = {
    readUrl: string;
    thumbnailUrl?: string;
}

export type UploadResult = FssReadUrl & {
    storageUrl: string;
}

export function getUploadUrl(scene: string, scope?: string, app?: string) {
    let url = ':fss/upload/scene';
    if (app) {
        url = ':' + app + '/' + url;
    }
    url = toRequestUrl(url);
    if (scope) {
        url += '?scope=' + scope;
    }
    return url;
}

const uploadLimitMap = new Map<String, UploadLimit>();

export async function getUploadLimit(scene: string): Promise<UploadLimit> {
    let limit = uploadLimitMap.get(scene);
    if (!limit) {
        limit = await get<UploadLimit>(':fss/limit/' + scene);
        if (limit) {
            uploadLimitMap.set(scene, limit);
        }
    }
    return limit;
}

export async function getUploadExtensions(scene: string): Promise<string[]> {
    let limit = await getUploadLimit(scene);
    if (limit) {
        if (limit.extensionsRejected) {
            return ['*'];
        }
        return [].concat(limit.extensions); // 不直接返回引用数组，避免被外界修改缓存
    }
    return [];
}

export async function checkUploadFile(scene: string, tempFile: File): Promise<void> {
    let limit = uploadLimitMap.get(scene);
    if (limit) {
        if (limit.extensions) {
            let filename = tempFile.name;
            let dotIndex = filename.lastIndexOf('.');
            let extension = dotIndex >= 0 ? filename.substring(dotIndex + 1) : '';
            if (limit.extensionsRejected) { // 扩展名拒绝模式
                if (limit.extensions.includes(extension.toLocaleLowerCase())) {
                    throw new Error('不可用的文件扩展名：' + limit.extensions.join(', '));
                }
            } else { // 扩展名接受模式
                if (!limit.extensions.includes(extension.toLocaleLowerCase())) {
                    throw new Error('不支持的文件扩展名。仅支持：' + limit.extensions.join(', '));
                }
            }
        }
        if (limit.capacityBytes && tempFile.size > limit.capacityBytes) {
            throw new Error('文件大小不能超过 ' + StringUtil.getCapacityCaption(limit.capacityBytes));
        }
    }
}

export function upload(file: File, scene: string, scope?: string): Promise<UploadResult> {
    const data = new FormData();
    data.append('file', file);
    if (scope) {
        data.append('scope', scope);
    }
    return uploadFile<UploadResult>(':fss/upload/' + scene, data);
}

export function getReadUrl(storageUrl: string, withThumbnail: boolean = false): Promise<FssReadUrl> {
    return get<FssReadUrl>(':fss/url/read', {storageUrl: encodeURIComponent(storageUrl), withThumbnail});
}
