"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UploadService = exports.NotCancellableError = exports.UploadPreviouslyFinalizedError = exports.UploadNotActiveError = exports.UploadStatus = exports.UploadType = void 0;
const uuid_1 = require("uuid");
const errors_1 = require("./errors");
var UploadType;
(function (UploadType) {
    UploadType[UploadType["MEDIA"] = 0] = "MEDIA";
    UploadType[UploadType["MULTIPART"] = 1] = "MULTIPART";
    UploadType[UploadType["RESUMABLE"] = 2] = "RESUMABLE";
})(UploadType = exports.UploadType || (exports.UploadType = {}));
var UploadStatus;
(function (UploadStatus) {
    UploadStatus[UploadStatus["ACTIVE"] = 0] = "ACTIVE";
    UploadStatus[UploadStatus["CANCELLED"] = 1] = "CANCELLED";
    UploadStatus[UploadStatus["FINISHED"] = 2] = "FINISHED";
})(UploadStatus = exports.UploadStatus || (exports.UploadStatus = {}));
class UploadNotActiveError extends Error {
}
exports.UploadNotActiveError = UploadNotActiveError;
class UploadPreviouslyFinalizedError extends Error {
}
exports.UploadPreviouslyFinalizedError = UploadPreviouslyFinalizedError;
class NotCancellableError extends Error {
}
exports.NotCancellableError = NotCancellableError;
class UploadService {
    constructor(_persistence) {
        this._persistence = _persistence;
        this.reset();
    }
    reset() {
        this._uploads = new Map();
    }
    mediaUpload(request) {
        const upload = this.startOneShotUpload({
            bucketId: request.bucketId,
            objectId: request.objectId,
            uploadType: UploadType.MEDIA,
            dataRaw: request.dataRaw,
            authorization: request.authorization,
        });
        this._persistence.deleteFile(upload.path, true);
        this._persistence.appendBytes(upload.path, request.dataRaw);
        return upload;
    }
    multipartUpload(request) {
        const upload = this.startOneShotUpload({
            bucketId: request.bucketId,
            objectId: request.objectId,
            uploadType: UploadType.MULTIPART,
            dataRaw: request.dataRaw,
            metadata: request.metadata,
            authorization: request.authorization,
        });
        this._persistence.deleteFile(upload.path, true);
        this._persistence.appendBytes(upload.path, request.dataRaw);
        return upload;
    }
    startOneShotUpload(request) {
        const id = (0, uuid_1.v4)();
        const upload = {
            id,
            bucketId: request.bucketId,
            objectId: request.objectId,
            type: request.uploadType,
            path: this.getStagingFileName(id, request.bucketId, request.objectId),
            status: UploadStatus.FINISHED,
            metadata: request.metadata,
            size: request.dataRaw.byteLength,
            authorization: request.authorization,
        };
        this._uploads.set(upload.id, upload);
        return upload;
    }
    startResumableUpload(request) {
        const id = (0, uuid_1.v4)();
        const upload = {
            id: id,
            bucketId: request.bucketId,
            objectId: request.objectId,
            type: UploadType.RESUMABLE,
            path: this.getStagingFileName(id, request.bucketId, request.objectId),
            status: UploadStatus.ACTIVE,
            metadata: request.metadata,
            size: 0,
            authorization: request.authorization,
        };
        this._uploads.set(upload.id, upload);
        this._persistence.deleteFile(upload.path, true);
        this._persistence.appendBytes(upload.path, Buffer.alloc(0));
        return upload;
    }
    continueResumableUpload(uploadId, dataRaw) {
        const upload = this.getResumableUpload(uploadId);
        if (upload.status !== UploadStatus.ACTIVE) {
            throw new UploadNotActiveError();
        }
        this._persistence.appendBytes(upload.path, dataRaw);
        upload.size += dataRaw.byteLength;
        return upload;
    }
    getResumableUpload(uploadId) {
        const upload = this._uploads.get(uploadId);
        if (!upload || upload.type !== UploadType.RESUMABLE) {
            throw new errors_1.NotFoundError();
        }
        return upload;
    }
    cancelResumableUpload(uploadId) {
        const upload = this.getResumableUpload(uploadId);
        if (upload.status === UploadStatus.FINISHED) {
            throw new NotCancellableError();
        }
        upload.status = UploadStatus.CANCELLED;
        return upload;
    }
    finalizeResumableUpload(uploadId) {
        const upload = this.getResumableUpload(uploadId);
        if (upload.status === UploadStatus.FINISHED) {
            throw new UploadPreviouslyFinalizedError();
        }
        if (upload.status === UploadStatus.CANCELLED) {
            throw new UploadNotActiveError();
        }
        upload.status = UploadStatus.FINISHED;
        return upload;
    }
    setResponseCode(uploadId, code) {
        const upload = this._uploads.get(uploadId);
        if (upload) {
            upload.prevResponseCode = code;
        }
    }
    getPreviousResponseCode(uploadId) {
        var _a;
        return ((_a = this._uploads.get(uploadId)) === null || _a === void 0 ? void 0 : _a.prevResponseCode) || 200;
    }
    getStagingFileName(uploadId, bucketId, objectId) {
        return encodeURIComponent(`${uploadId}_b_${bucketId}_o_${objectId}`);
    }
}
exports.UploadService = UploadService;
//# sourceMappingURL=upload.js.map