/**
 * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
import { decode } from 'blurhash';
/**
 * Converts image source set provided by the CKBox into an object containing:
 * - responsive URLs for the "webp" image format,
 * - one fallback URL for browsers that do not support the "webp" format.
 */
export function getImageUrls(imageUrls) {
    const responsiveUrls = [];
    let maxWidth = 0;
    for (const key in imageUrls) {
        const width = parseInt(key, 10);
        if (!isNaN(width)) {
            if (width > maxWidth) {
                maxWidth = width;
            }
            responsiveUrls.push(`${imageUrls[key]} ${key}w`);
        }
    }
    const imageSources = [{
            srcset: responsiveUrls.join(','),
            sizes: `(max-width: ${maxWidth}px) 100vw, ${maxWidth}px`,
            type: 'image/webp'
        }];
    return {
        imageFallbackUrl: imageUrls.default,
        imageSources
    };
}
/**
 * Returns a workspace id to use for communication with the CKBox service.
 *
 * @param defaultWorkspaceId The default workspace to use taken from editor config.
 */
export function getWorkspaceId(token, defaultWorkspaceId) {
    const [, binaryTokenPayload] = token.value.split('.');
    const payload = JSON.parse(atob(binaryTokenPayload));
    const workspaces = (payload.auth && payload.auth.ckbox && payload.auth.ckbox.workspaces) || [payload.aud];
    if (!defaultWorkspaceId) {
        return workspaces[0];
    }
    const role = payload.auth && payload.auth.ckbox && payload.auth.ckbox.role;
    if (role == 'superadmin' || workspaces.includes(defaultWorkspaceId)) {
        return defaultWorkspaceId;
    }
    return null;
}
/**
 * Default resolution for decoding blurhash values.
 * Relatively small values must be used in order to ensure acceptable performance.
 */
const BLUR_RESOLUTION = 32;
/**
 * Generates an image data URL from its `blurhash` representation.
 */
export function blurHashToDataUrl(hash) {
    if (!hash) {
        return;
    }
    try {
        const resolutionInPx = `${BLUR_RESOLUTION}px`;
        const canvas = document.createElement('canvas');
        canvas.setAttribute('width', resolutionInPx);
        canvas.setAttribute('height', resolutionInPx);
        const ctx = canvas.getContext('2d');
        /* istanbul ignore next -- @preserve */
        if (!ctx) {
            return;
        }
        const imageData = ctx.createImageData(BLUR_RESOLUTION, BLUR_RESOLUTION);
        const decoded = decode(hash, BLUR_RESOLUTION, BLUR_RESOLUTION);
        imageData.data.set(decoded);
        ctx.putImageData(imageData, 0, 0);
        return canvas.toDataURL();
    }
    catch (e) {
        return undefined;
    }
}
/**
 * Sends the HTTP request.
 *
 * @internal
 * @param config.url the URL where the request will be sent.
 * @param config.method The HTTP method.
 * @param config.data Additional data to send.
 * @param config.onUploadProgress A callback informing about the upload progress.
 */
export function sendHttpRequest({ url, method = 'GET', data, onUploadProgress, signal, authorization }) {
    const xhr = new XMLHttpRequest();
    xhr.open(method, url.toString());
    xhr.setRequestHeader('Authorization', authorization);
    xhr.setRequestHeader('CKBox-Version', 'CKEditor 5');
    xhr.responseType = 'json';
    // The callback is attached to the `signal#abort` event.
    const abortCallback = () => {
        xhr.abort();
    };
    return new Promise((resolve, reject) => {
        signal.throwIfAborted();
        signal.addEventListener('abort', abortCallback);
        xhr.addEventListener('loadstart', () => {
            signal.addEventListener('abort', abortCallback);
        });
        xhr.addEventListener('loadend', () => {
            signal.removeEventListener('abort', abortCallback);
        });
        xhr.addEventListener('error', () => {
            reject();
        });
        xhr.addEventListener('abort', () => {
            reject();
        });
        xhr.addEventListener('load', () => {
            const response = xhr.response;
            if (!response || response.statusCode >= 400) {
                return reject(response && response.message);
            }
            resolve(response);
        });
        /* istanbul ignore else -- @preserve */
        if (onUploadProgress) {
            xhr.upload.addEventListener('progress', evt => {
                onUploadProgress(evt);
            });
        }
        // Send the request.
        xhr.send(data);
    });
}
const MIME_TO_EXTENSION = {
    'image/gif': 'gif',
    'image/jpeg': 'jpg',
    'image/png': 'png',
    'image/webp': 'webp',
    'image/bmp': 'bmp',
    'image/tiff': 'tiff'
};
/**
 * Returns an extension a typical file in the specified `mimeType` format would have.
 */
export function convertMimeTypeToExtension(mimeType) {
    return MIME_TO_EXTENSION[mimeType];
}
/**
 * Tries to fetch the given `url` and returns 'content-type' of the response.
 */
export async function getContentTypeOfUrl(url, options) {
    try {
        const response = await fetch(url, {
            method: 'HEAD',
            cache: 'force-cache',
            ...options
        });
        if (!response.ok) {
            return '';
        }
        return response.headers.get('content-type') || '';
    }
    catch {
        return '';
    }
}
/**
 * Returns an extension from the given value.
 */
export function getFileExtension(file) {
    const fileName = file.name;
    const extensionRegExp = /\.(?<ext>[^.]+)$/;
    const match = fileName.match(extensionRegExp);
    return match.groups.ext.toLowerCase();
}
