"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const crypto_1 = require("crypto");
const FormData = require("form-data");
const fs_1 = require("fs");
const errors_1 = require("../errors");
/**
 * Uploader tosses a packaged bundle to the Mixer servers.
 */
class Uploader {
    constructor(requester, project) {
        this.requester = requester;
        this.project = project;
    }
    /**
     * Uploads the bundle output to
     */
    upload(filename) {
        return __awaiter(this, void 0, void 0, function* () {
            const config = yield this.project.packageConfig();
            const checksum = yield this.makeChecksum(filename);
            const form = new FormData();
            form.append('checksum', checksum);
            form.append('metadata', JSON.stringify(config));
            form.append('tarball', fs_1.createReadStream(filename));
            const path = `/interactive/bundles/${config.name}/versions/${config.version}/tarball`;
            return this.requester
                .run(path, {
                method: 'PUT',
                headers: form.getHeaders(),
                body: form,
            })
                .then((res) => __awaiter(this, void 0, void 0, function* () {
                if (res.status < 300) {
                    return;
                }
                if (res.status === 403) {
                    throw new errors_1.BundleNameTakenError(res, yield res.text());
                }
                throw new errors_1.UploaderHttpError(res, yield res.text());
            }));
        });
    }
    makeChecksum(filename) {
        return __awaiter(this, void 0, void 0, function* () {
            return new Promise((resolve, reject) => {
                fs_1.createReadStream(filename)
                    .pipe(crypto_1.createHash('sha512'))
                    .on('error', reject)
                    .on('data', (hash) => {
                    resolve(hash.toString('hex').slice(0, 64));
                });
            });
        });
    }
}
exports.Uploader = Uploader;
