"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
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.resolutionTestUtils = void 0;
const internal_1 = require("../../../internal");
const testHelper_1 = require("../../testHelper");
/**
 * Common utilities used by resolution tests.
 */
exports.resolutionTestUtils = {
    /**
     * Function used to test resolving an environment.
     * Writes a helper function used for debugging.
     * Asserts the result matches the expected result stored in a file.
     * @param testsSubPath Tests sub-folder name
     * @param testName The name of the test. It is used to decide the path of input / output files.
     * @param manifestName The name of the manifest to be used.
     */
    resolveSaveDebuggingFileAndAssert(testsSubPath, testName, manifestName, doesWriteDebuggingFiles = true) {
        return __awaiter(this, void 0, void 0, function* () {
            const result = (yield exports.resolutionTestUtils.resolveEnvironment(testsSubPath, testName, manifestName));
            const outputFileName = `${manifestName}.txt`;
            if (doesWriteDebuggingFiles) {
                testHelper_1.testHelper.writeActualOutputFileContent(testsSubPath, testName, outputFileName, result);
            }
            const original = testHelper_1.testHelper.getExpectedOutputFileContent(testsSubPath, testName, outputFileName);
            testHelper_1.testHelper.assertFileContentEquality(result, original);
        });
    },
    /**
     * Resolve the entities in the given manifest
     * @param testsSubPath Tests sub-folder name
     * @param testName The name of the test. It is used to decide the path of input / output files.
     * @param manifestName The name of the manifest to be used.
     * @return the resolved manifest as a promise.
     */
    resolveEnvironment(testsSubPath, testName, manifestName) {
        return __awaiter(this, void 0, void 0, function* () {
            const inputFileName = `local:/${manifestName}.manifest.cdm.json`;
            const cdmCorpus = testHelper_1.testHelper.getLocalCorpus(testsSubPath, testName);
            const manifest = yield cdmCorpus.createRootManifest(inputFileName);
            const directives = new internal_1.AttributeResolutionDirectiveSet(new Set(['normalized', 'referenceOnly']));
            return yield exports.resolutionTestUtils.listAllResolved(cdmCorpus, directives, manifest, new internal_1.stringSpewCatcher());
        });
    },
    /**
     * @internal
     * Get the text version of all the resolved entities.
     * @param cdmCorpus The CDM corpus.
     * @param directives The directives to use while getting the resolved entities.
     * @param manifest The manifest to be resolved.
     * @param spew The object used to store the text to be returned.
     * @returns The text version of the resolved entities. (it's in a form that facilitates debugging)
     */
    listAllResolved(cdmCorpus, directives, manifest, spew) {
        return __awaiter(this, void 0, void 0, function* () {
            const seen = new Set();
            // make sure the corpus has a set of default artifact attributes
            yield cdmCorpus.prepareArtifactAttributesAsync();
            function seekEntities(f) {
                return __awaiter(this, void 0, void 0, function* () {
                    if (f && f.entities) {
                        if (spew) {
                            spew.spewLine(f.folderPath);
                        }
                        for (const entity of f.entities) {
                            let corpusPath;
                            let ent = entity;
                            let currentFile = f;
                            while ((0, internal_1.isReferencedEntityDeclarationDefinition)(ent)) {
                                corpusPath =
                                    cdmCorpus.storage.createAbsoluteCorpusPath(ent.entityPath, currentFile);
                                ent = yield cdmCorpus.fetchObjectAsync(corpusPath);
                                currentFile = ent;
                            }
                            corpusPath = cdmCorpus.storage.createAbsoluteCorpusPath(ent.entityPath, currentFile);
                            const resOpt = new internal_1.resolveOptions();
                            resOpt.importsLoadStrategy = internal_1.importsLoadStrategy.load;
                            const newEnt = yield cdmCorpus.fetchObjectAsync(corpusPath, undefined, resOpt);
                            resOpt.wrtDoc = newEnt.inDocument;
                            resOpt.directives = directives;
                            const resEnt = new internal_1.ResolvedEntity(resOpt, newEnt);
                            if (spew) {
                                resEnt.spew(resOpt, spew, ' ', true);
                            }
                        }
                    }
                    if (f && f.subManifests) {
                        for (const subManifest of f.subManifests) {
                            const corpusPath = cdmCorpus.storage.createAbsoluteCorpusPath(subManifest.definition, f);
                            yield seekEntities(yield cdmCorpus.fetchObjectAsync(corpusPath));
                        }
                    }
                });
            }
            yield seekEntities(manifest);
            if (spew) {
                return spew.getContent();
            }
            return '';
        });
    }
};
//# sourceMappingURL=ResolutionTestUtils.js.map