"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseTestsTreeBuilder = void 0;
const lodash_1 = __importDefault(require("lodash"));
const common_utils_1 = require("../common-utils");
const constants_1 = require("../constants");
const tree_1 = require("../test-adapter/transformers/tree");
class BaseTestsTreeBuilder {
    static create(options) {
        return new this(options);
    }
    constructor({ toolName, baseHost }) {
        this._toolName = toolName;
        this._transformer = new tree_1.TreeTestResultTransformer({ baseHost });
        this._tree = {
            suites: { byId: {}, allIds: [], allRootIds: [] },
            browsers: { byId: {}, allIds: [] },
            results: { byId: {}, allIds: [] },
            images: { byId: {}, allIds: [] }
        };
    }
    get tree() {
        return this._tree;
    }
    sortTree() {
        const sortChildSuites = (suiteId) => {
            const childSuite = this._tree.suites.byId[suiteId];
            if (childSuite.suiteIds) {
                childSuite.suiteIds.sort().forEach(sortChildSuites);
            }
            if (childSuite.browserIds) {
                childSuite.browserIds.sort();
            }
        };
        this._tree.suites.allRootIds.sort().forEach(sortChildSuites);
    }
    addTestResult(formattedResult) {
        const { testPath, browserId: browserName, attempt, imagesInfo = [] } = formattedResult;
        const { browserVersion = constants_1.BrowserVersions.UNKNOWN } = formattedResult.meta;
        const suiteId = this._buildId(testPath);
        const browserId = this._buildId(suiteId, browserName);
        const testResultId = this._buildId(browserId, attempt.toString());
        const imageIds = imagesInfo
            .map((image, i) => this._buildId(testResultId, image.stateName || `${image.status}_${i}`));
        this._addSuites(testPath, browserId);
        this._addBrowser({ id: browserId, parentId: suiteId, name: browserName, version: browserVersion }, testResultId, attempt);
        this._addResult({ id: testResultId, parentId: browserId, result: formattedResult }, imageIds);
        this._addImages(imageIds, { imagesInfo, parentId: testResultId });
        this._setStatusForBranch(testPath);
    }
    _buildId(parentId = [], name = []) {
        const delimiter = this._toolName === constants_1.ToolName.Playwright ? constants_1.PWT_TITLE_DELIMITER : constants_1.TESTPLANE_TITLE_DELIMITER;
        return [].concat(parentId, name).join(delimiter);
    }
    _addSuites(testPath, browserId) {
        testPath.reduce((suites, name, ind, arr) => {
            const isRoot = ind === 0;
            const suitePath = isRoot ? [name] : arr.slice(0, ind + 1);
            const id = this._buildId(suitePath);
            if (!suites.byId[id]) {
                const parentId = isRoot ? null : this._buildId(suitePath.slice(0, -1));
                const suite = { id, parentId, name, suitePath, root: isRoot };
                this._addSuite(suite);
            }
            if (ind !== arr.length - 1) {
                const childSuiteId = this._buildId(id, arr[ind + 1]);
                this._addNodeId(id, childSuiteId, { fieldName: 'suiteIds' });
            }
            else {
                this._addNodeId(id, browserId, { fieldName: 'browserIds' });
            }
            return suites;
        }, this._tree.suites);
    }
    _addSuite(suite) {
        const { suites } = this._tree;
        suites.byId[suite.id] = suite;
        suites.allIds.push(suite.id);
        if (suite.root) {
            suites.allRootIds.push(suite.id);
        }
    }
    _addNodeId(parentSuiteId, nodeId, { fieldName }) {
        const { suites } = this._tree;
        if (!suites.byId[parentSuiteId][fieldName]) {
            suites.byId[parentSuiteId][fieldName] = [nodeId];
            return;
        }
        if (!this._isNodeIdExists(parentSuiteId, nodeId, { fieldName })) {
            suites.byId[parentSuiteId][fieldName]?.push(nodeId);
        }
    }
    _isNodeIdExists(parentSuiteId, nodeId, { fieldName }) {
        return lodash_1.default.includes(this._tree.suites.byId[parentSuiteId][fieldName], nodeId);
    }
    _addBrowser({ id, parentId, name, version }, testResultId, attempt) {
        const { browsers } = this._tree;
        if (!browsers.byId[id]) {
            browsers.byId[id] = { id, parentId, name, resultIds: [], version };
            browsers.allIds.push(id);
        }
        this._addResultIdToBrowser(id, testResultId, attempt);
    }
    _addResultIdToBrowser(browserId, testResultId, attempt) {
        this._tree.browsers.byId[browserId].resultIds[attempt] = testResultId;
    }
    _addResult({ id, parentId, result }, imageIds) {
        const treeResult = this._transformer.transform(result);
        if (!this._tree.results.byId[id]) {
            this._tree.results.allIds.push(id);
        }
        this._tree.results.byId[id] = { attempt: 0, id, parentId, ...treeResult, imageIds };
    }
    _addImages(imageIds, { imagesInfo, parentId }) {
        imageIds.forEach((id, ind) => {
            this._tree.images.byId[id] = { ...imagesInfo[ind], id, parentId };
            this._tree.images.allIds.push(id);
        });
    }
    _setStatusForBranch(testPath = []) {
        const suiteId = this._buildId(testPath);
        if (!suiteId) {
            return;
        }
        const suite = this._tree.suites.byId[suiteId];
        const resultStatuses = lodash_1.default.compact([].concat(suite.browserIds))
            .map((browserId) => {
            const browser = this._tree.browsers.byId[browserId];
            const lastResultId = lodash_1.default.last(browser.resultIds);
            return this._tree.results.byId[lastResultId].status;
        });
        const childrenSuiteStatuses = lodash_1.default.compact([].concat(suite.suiteIds))
            .map((childSuiteId) => this._tree.suites.byId[childSuiteId].status);
        const status = (0, common_utils_1.determineFinalStatus)(lodash_1.default.compact([...resultStatuses, ...childrenSuiteStatuses]));
        // if newly determined status is the same as current status, do nothing
        if (suite.status === status) {
            return;
        }
        suite.status = status || undefined;
        this._setStatusForBranch(testPath.slice(0, -1));
    }
}
exports.BaseTestsTreeBuilder = BaseTestsTreeBuilder;
//# sourceMappingURL=base.js.map