"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = require("path");
const collectByKey_1 = require("../common/collectByKey");
const flatten_1 = require("../common/flatten");
function generateTestBundle(cwd, fileDirectory, port, timeout, metadata) {
    const stats = { numberOfTests: 0, testToTestNumber: {} };
    const metadataByFilePath = collectByKey_1.collectByKey(x => x.filePath, metadata);
    const filePaths = Object.keys(metadataByFilePath);
    const relativePath = path_1.relative(fileDirectory, __dirname);
    const importStatements = filePaths.map(filePath => buildImportStatement(fileDirectory, stats, filePath, metadataByFilePath[filePath]));
    return [
        importStatements.join(`\n`),
        createTestsWithMetadata(stats.testToTestNumber, metadata),
        createApi(cwd, relativePath, port, timeout),
        createTestRun(relativePath),
        `\n`,
    ].join(`\n`);
}
exports.generateTestBundle = generateTestBundle;
function createTestRun(relativePath) {
    return [
        `import { run } from '${path_1.join(relativePath, 'runTestsAndReport')}'`,
        `\n`,
        `run(TypedTest)`,
    ].join(`\n`);
}
function createApi(cwd, relativePath, port, timeout) {
    return [
        `const retrieveMetadata = () => Promise.resolve(TYPED_TEST_METADATA)`,
        `import { reportResults, logger } from '${path_1.join(relativePath, 'api')}'`,
        `import { runTests } from '${path_1.join(relativePath, '../common/runTests')}'`,
        `const TypedTest = Object.freeze({
      cwd: '${cwd}',
      retrieveMetadata,
      reportResults,
      runTests,
      logger,
      TIMEOUT: ${timeout},
      PORT: ${port}
    })`,
        `export = TypedTest`,
    ].join(`\n`);
}
function createTestsWithMetadata(testToTestNumber, metadata) {
    const tests = metadata.map(m => {
        const testNames = findTestNames(m).map(x => `test${testToTestNumber[x]}`);
        return `\n  Object.assign({}, ${JSON.stringify(m)}, { tests: [${testNames.join(', ')}] })`;
    });
    return `const TYPED_TEST_METADATA = [` + tests.join(',') + `\n]\n\n`;
}
function findTestNames({ exportNames, filePath }) {
    return exportNames.map(x => `${filePath}/${x}`);
}
function buildImportStatement(fileDirectory, stats, filePath, metadata) {
    const exportNames = flatten_1.chain(x => x.exportNames, metadata);
    const importSpecifiers = [];
    for (const exportName of exportNames) {
        const testName = `${filePath}/${exportName}`;
        const testNum = stats.numberOfTests;
        const specifier = ` ${exportName} as test${testNum}`;
        stats.testToTestNumber[testName] = testNum;
        stats.numberOfTests++;
        importSpecifiers.push(specifier);
    }
    const moduleSpecificer = path_1.relative(fileDirectory, filePath.replace(/\.ts(x)?$/, ''));
    return `import {${importSpecifiers.join(',')} } from '${moduleSpecificer}'`;
}
//# sourceMappingURL=generateTestBundle.js.map