"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.uploadCollection = exports.downloadFileReadable = exports.downloadFile = exports.uploadFile = void 0;
const headers_1 = require("../utils/headers");
const http_1 = require("../utils/http");
const data_1 = require("../utils/data");
const tar_1 = require("../utils/tar");
const collection_1 = require("../utils/collection");
const bytes_1 = require("../utils/bytes");
const stream_1 = require("../utils/stream");
const type_1 = require("../utils/type");
const bzzEndpoint = 'bzz';
function extractFileUploadHeaders(postageBatchId, options) {
    const headers = (0, headers_1.extractUploadHeaders)(postageBatchId, options);
    if (options === null || options === void 0 ? void 0 : options.size)
        headers['content-length'] = String(options.size);
    if (options === null || options === void 0 ? void 0 : options.contentType)
        headers['content-type'] = options.contentType;
    return headers;
}
/**
 * Upload single file
 *
 * @param ky
 * @param data Files data
 * @param postageBatchId  Postage BatchId that will be assigned to uploaded data
 * @param name Name that will be attached to the uploaded file. Wraps the data into manifest with set index document.
 * @param options
 */
function uploadFile(ky, data, postageBatchId, name, options) {
    return __awaiter(this, void 0, void 0, function* () {
        if ((0, stream_1.isReadable)(data) && !(options === null || options === void 0 ? void 0 : options.contentType)) {
            if (!options)
                options = {};
            options.contentType = 'application/octet-stream';
        }
        const response = yield (0, http_1.http)(ky, {
            method: 'post',
            path: bzzEndpoint,
            body: yield (0, data_1.prepareData)(data),
            headers: Object.assign({}, extractFileUploadHeaders(postageBatchId, options)),
            searchParams: { name },
            responseType: 'json',
        });
        return {
            reference: response.data.reference,
            tagUid: (0, type_1.makeTagUid)(response.headers.get('swarm-tag')),
        };
    });
}
exports.uploadFile = uploadFile;
/**
 * Download single file as a buffer
 *
 * @param ky Ky instance for given Bee class instance
 * @param hash Bee file or collection hash
 * @param path If hash is collection then this defines path to a single file in the collection
 */
function downloadFile(ky, hash, path = '') {
    return __awaiter(this, void 0, void 0, function* () {
        const response = yield (0, http_1.http)(ky, {
            method: 'GET',
            responseType: 'arraybuffer',
            path: `${bzzEndpoint}/${hash}/${path}`,
        });
        const file = Object.assign(Object.assign({}, (0, headers_1.readFileHeaders)(response.headers)), { data: (0, bytes_1.wrapBytesWithHelpers)(new Uint8Array(response.data)) });
        return file;
    });
}
exports.downloadFile = downloadFile;
/**
 * Download single file as a readable stream
 *
 * @param ky Ky instance for given Bee class instance
 * @param hash Bee file or collection hash
 * @param path If hash is collection then this defines path to a single file in the collection
 */
function downloadFileReadable(ky, hash, path = '') {
    return __awaiter(this, void 0, void 0, function* () {
        const response = yield (0, http_1.http)(ky, {
            method: 'GET',
            responseType: 'stream',
            path: `${bzzEndpoint}/${hash}/${path}`,
        });
        const file = Object.assign(Object.assign({}, (0, headers_1.readFileHeaders)(response.headers)), { data: response.data });
        return file;
    });
}
exports.downloadFileReadable = downloadFileReadable;
function extractCollectionUploadHeaders(postageBatchId, options) {
    const headers = (0, headers_1.extractUploadHeaders)(postageBatchId, options);
    if (options === null || options === void 0 ? void 0 : options.indexDocument)
        headers['swarm-index-document'] = options.indexDocument;
    if (options === null || options === void 0 ? void 0 : options.errorDocument)
        headers['swarm-error-document'] = options.errorDocument;
    return headers;
}
/**
 * Upload collection
 * @param ky Ky instance for given Bee class instance
 * @param collection Collection of Uint8Array buffers to upload
 * @param postageBatchId  Postage BatchId that will be assigned to uploaded data
 * @param options
 */
function uploadCollection(ky, collection, postageBatchId, options) {
    return __awaiter(this, void 0, void 0, function* () {
        (0, collection_1.assertCollection)(collection);
        const tarData = (0, tar_1.makeTar)(collection);
        const response = yield (0, http_1.http)(ky, {
            method: 'post',
            path: bzzEndpoint,
            body: tarData,
            responseType: 'json',
            headers: Object.assign({ 'content-type': 'application/x-tar', 'swarm-collection': 'true' }, extractCollectionUploadHeaders(postageBatchId, options)),
        });
        return {
            reference: response.data.reference,
            tagUid: (0, type_1.makeTagUid)(response.headers.get('swarm-tag')),
        };
    });
}
exports.uploadCollection = uploadCollection;
