import { defaultStorage } from '@aws-amplify/core';
import { UPLOADS_STORAGE_KEY } from '../../../utils/constants.mjs';
import '../../../utils/client/base.mjs';
import '../../../utils/client/getObject.mjs';
import '../../../utils/client/listObjectsV2.mjs';
import '../../../utils/client/putObject.mjs';
import '../../../utils/client/createMultipartUpload.mjs';
import '../../../utils/client/uploadPart.mjs';
import '../../../utils/client/completeMultipartUpload.mjs';
import { listParts } from '../../../utils/client/listParts.mjs';
import '../../../utils/client/abortMultipartUpload.mjs';
import '../../../utils/client/copyObject.mjs';
import '../../../utils/client/headObject.mjs';
import '../../../utils/client/deleteObject.mjs';
import '../../../../../errors/types/validation.mjs';
import '@aws-amplify/core/internals/utils';
import { logger } from '../../../../../utils/logger.mjs';

// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
const ONE_HOUR = 1000 * 60 * 60;
/**
 * Find the cached multipart upload id and get the parts that have been uploaded
 * with ListParts API. If the cached upload is expired(1 hour), return null.
 */
const findCachedUploadParts = async ({ cacheKey, s3Config, bucket, finalKey, }) => {
    const cachedUploads = await listCachedUploadTasks(defaultStorage);
    if (!cachedUploads[cacheKey] ||
        cachedUploads[cacheKey].lastTouched < Date.now() - ONE_HOUR // Uploads are cached for 1 hour
    ) {
        return null;
    }
    const cachedUpload = cachedUploads[cacheKey];
    cachedUpload.lastTouched = Date.now();
    await defaultStorage.setItem(UPLOADS_STORAGE_KEY, JSON.stringify(cachedUploads));
    try {
        const { Parts = [] } = await listParts(s3Config, {
            Bucket: bucket,
            Key: finalKey,
            UploadId: cachedUpload.uploadId,
        });
        return {
            parts: Parts,
            uploadId: cachedUpload.uploadId,
        };
    }
    catch (e) {
        logger.debug('failed to list cached parts, removing cached upload.');
        await removeCachedUpload(cacheKey);
        return null;
    }
};
const listCachedUploadTasks = async (kvStorage) => {
    try {
        return JSON.parse((await kvStorage.getItem(UPLOADS_STORAGE_KEY)) ?? '{}');
    }
    catch (e) {
        logger.debug('failed to parse cached uploads record.');
        return {};
    }
};
/**
 * Get the cache key of a multipart upload. Data source cached by different: size, content type, bucket, access level,
 * key. If the data source is a File instance, the upload is additionally indexed by file name and last modified time.
 * So the library always created a new multipart upload if the file is modified.
 */
const getUploadsCacheKey = ({ file, size, contentType, bucket, accessLevel, key, }) => {
    const resolvedContentType = contentType ?? file?.type ?? 'application/octet-stream';
    const levelStr = accessLevel === 'guest' ? 'public' : accessLevel;
    const baseId = `${size}_${resolvedContentType}_${bucket}_${levelStr}_${key}`;
    if (file) {
        return `${file.name}_${file.lastModified}_${baseId}`;
    }
    else {
        return baseId;
    }
};
const cacheMultipartUpload = async (cacheKey, fileMetadata) => {
    const cachedUploads = await listCachedUploadTasks(defaultStorage);
    cachedUploads[cacheKey] = {
        ...fileMetadata,
        lastTouched: Date.now(),
    };
    await defaultStorage.setItem(UPLOADS_STORAGE_KEY, JSON.stringify(cachedUploads));
};
const removeCachedUpload = async (cacheKey) => {
    const cachedUploads = await listCachedUploadTasks(defaultStorage);
    delete cachedUploads[cacheKey];
    await defaultStorage.setItem(UPLOADS_STORAGE_KEY, JSON.stringify(cachedUploads));
};

export { cacheMultipartUpload, findCachedUploadParts, getUploadsCacheKey, removeCachedUpload };
//# sourceMappingURL=uploadCache.mjs.map
