"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 logger_1 = require("@pnpm/logger");
const http = require("http");
const lock_1 = require("./lock");
function default_1(store, opts) {
    const rawManifestPromises = {};
    const filesPromises = {};
    const lock = lock_1.default();
    const server = http.createServer((req, res) => __awaiter(this, void 0, void 0, function* () {
        if (req.method !== 'POST') {
            res.statusCode = 503;
            res.end(JSON.stringify(`Only POST is allowed, received ${req.method}`));
            return;
        }
        const bodyPromise = new Promise((resolve, reject) => {
            let body = ''; // tslint:disable-line
            req.on('data', (data) => {
                body += data;
            });
            req.on('end', () => __awaiter(this, void 0, void 0, function* () {
                try {
                    if (body.length > 0) {
                        body = JSON.parse(body);
                    }
                    else {
                        body = {};
                    }
                    resolve(body);
                }
                catch (e) {
                    reject(e);
                }
            }));
        });
        try {
            let body;
            switch (req.url) {
                case '/requestPackage': {
                    body = yield bodyPromise;
                    const pkgResponse = yield store.requestPackage(body.wantedDependency, body.options);
                    if (pkgResponse['fetchingRawManifest']) { // tslint:disable-line
                        rawManifestPromises[body.msgId] = pkgResponse['fetchingRawManifest']; // tslint:disable-line
                        pkgResponse.body['fetchingRawManifestInProgress'] = true; // tslint:disable-line
                    }
                    if (pkgResponse['fetchingFiles']) { // tslint:disable-line
                        filesPromises[body.msgId] = pkgResponse['fetchingFiles']; // tslint:disable-line
                    }
                    res.end(JSON.stringify(pkgResponse.body));
                    break;
                }
                case '/fetchPackage': {
                    body = yield bodyPromise;
                    const pkgResponse = store.fetchPackage(body.options);
                    if (pkgResponse['fetchingRawManifest']) { // tslint:disable-line
                        rawManifestPromises[body.msgId] = pkgResponse['fetchingRawManifest']; // tslint:disable-line
                    }
                    if (pkgResponse['fetchingFiles']) { // tslint:disable-line
                        filesPromises[body.msgId] = pkgResponse['fetchingFiles']; // tslint:disable-line
                    }
                    res.end(JSON.stringify({ inStoreLocation: pkgResponse.inStoreLocation }));
                    break;
                }
                case '/packageFilesResponse':
                    body = yield bodyPromise;
                    const filesResponse = yield filesPromises[body.msgId];
                    delete filesPromises[body.msgId];
                    res.end(JSON.stringify(filesResponse));
                    break;
                case '/rawManifestResponse':
                    body = yield bodyPromise;
                    const manifestResponse = yield rawManifestPromises[body.msgId];
                    delete rawManifestPromises[body.msgId];
                    res.end(JSON.stringify(manifestResponse));
                    break;
                case '/updateConnections':
                    body = yield bodyPromise;
                    yield store.updateConnections(body.prefix, body.opts);
                    res.end(JSON.stringify('OK'));
                    break;
                case '/prune':
                    // Disable store pruning when a server is running
                    res.statusCode = 403;
                    res.end();
                    break;
                case '/saveState':
                    yield store.saveState();
                    res.end(JSON.stringify('OK'));
                    break;
                case '/importPackage':
                    const importPackageBody = (yield bodyPromise); // tslint:disable-line:no-any
                    yield store.importPackage(importPackageBody.from, importPackageBody.to, importPackageBody.opts);
                    res.end(JSON.stringify('OK'));
                    break;
                case '/upload':
                    // Do not return an error status code, just ignore the upload request entirely
                    if (opts.ignoreUploadRequests) {
                        res.statusCode = 403;
                        res.end();
                        break;
                    }
                    const uploadBody = (yield bodyPromise); // tslint:disable-line:no-any
                    yield lock(uploadBody.builtPkgLocation, () => store.upload(uploadBody.builtPkgLocation, uploadBody.opts));
                    res.end(JSON.stringify('OK'));
                    break;
                case '/stop':
                    if (opts.ignoreStopRequests) {
                        res.statusCode = 403;
                        res.end();
                        break;
                    }
                    logger_1.storeLogger.info('Got request to stop the server');
                    yield close();
                    res.end(JSON.stringify('OK'));
                    logger_1.storeLogger.info('Server stopped');
                    break;
                case '/getCacheByEngine':
                    body = yield bodyPromise;
                    res.end(JSON.stringify(yield store.getCacheByEngine(body.storePath, body.id)));
                    break;
                default:
                    res.statusCode = 404;
                    res.end(`${req.url} does not match any route`);
            }
        }
        catch (e) {
            res.statusCode = 503;
            const jsonErr = JSON.parse(JSON.stringify(e));
            jsonErr.message = e.message;
            res.end(JSON.stringify(jsonErr));
        }
    }));
    let listener;
    if (opts.path) {
        listener = server.listen(opts.path);
    }
    else {
        listener = server.listen(opts.port, opts.hostname);
    }
    return { close };
    function close() {
        listener.close();
        return store.close();
    }
}
exports.default = default_1;
//# sourceMappingURL=createServer.js.map