/**
 * Copyright (c) Microsoft Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import fs from 'fs';
import { monotonicTime } from '@isomorphic/time';
import { internalScreen, prepareErrorStack, relativeFilePath } from './base';
import { Multiplexer } from './multiplexer';
import { test as testNs } from '../common';
import * as babel from '../transform/babelBundle';
import { wrapReporterAsV2 } from './reporterV2';
export class InternalReporter {
    _reporter;
    _didBegin = false;
    _config;
    _startTime;
    _monotonicStartTime;
    constructor(reporters) {
        this._reporter = new Multiplexer(reporters.map(wrapReporterAsV2));
    }
    version() {
        return 'v2';
    }
    onConfigure(config) {
        this._config = config;
        this._startTime = new Date();
        this._monotonicStartTime = monotonicTime();
        this._reporter.onConfigure?.(config);
    }
    onBegin(suite) {
        this._didBegin = true;
        this._reporter.onBegin?.(suite);
    }
    onTestBegin(test, result) {
        this._reporter.onTestBegin?.(test, result);
    }
    onStdOut(chunk, test, result) {
        this._reporter.onStdOut?.(chunk, test, result);
    }
    onStdErr(chunk, test, result) {
        this._reporter.onStdErr?.(chunk, test, result);
    }
    async onTestPaused(test, result) {
        this._addSnippetToTestErrors(test, result);
        return await this._reporter.onTestPaused?.(test, result);
    }
    onTestEnd(test, result) {
        this._addSnippetToTestErrors(test, result);
        this._reporter.onTestEnd?.(test, result);
    }
    async onEnd(result) {
        if (!this._didBegin) {
            // onBegin was not reported, emit it.
            this.onBegin(new testNs.Suite('', 'root'));
        }
        return await this._reporter.onEnd?.({
            ...result,
            startTime: this._startTime,
            duration: monotonicTime() - this._monotonicStartTime,
        });
    }
    async onExit() {
        await this._reporter.onExit?.();
    }
    onError(error, workerInfo) {
        addLocationAndSnippetToError(this._config, error);
        this._reporter.onError?.(error, workerInfo);
    }
    onStepBegin(test, result, step) {
        this._reporter.onStepBegin?.(test, result, step);
    }
    onStepEnd(test, result, step) {
        this._addSnippetToStepError(test, step);
        this._reporter.onStepEnd?.(test, result, step);
    }
    printsToStdio() {
        return this._reporter.printsToStdio ? this._reporter.printsToStdio() : true;
    }
    _addSnippetToTestErrors(test, result) {
        for (const error of result.errors)
            addLocationAndSnippetToError(this._config, error, test.location.file);
    }
    _addSnippetToStepError(test, step) {
        if (step.error)
            addLocationAndSnippetToError(this._config, step.error, test.location.file);
    }
}
export function addLocationAndSnippetToError(config, error, file) {
    if (error.stack && !error.location)
        error.location = prepareErrorStack(error.stack).location;
    const location = error.location;
    if (!location)
        return;
    if (!!error.snippet)
        return;
    try {
        const tokens = [];
        const source = fs.readFileSync(location.file, 'utf8');
        const codeFrame = babel.codeFrameColumns(source, { start: location }, { highlightCode: true });
        // Convert /var/folders to /private/var/folders on Mac.
        if (!file || fs.realpathSync(file) !== location.file) {
            tokens.push(internalScreen.colors.gray(`   at `) + `${relativeFilePath(internalScreen, config, location.file)}:${location.line}`);
            tokens.push('');
        }
        tokens.push(codeFrame);
        error.snippet = tokens.join('\n');
    }
    catch (e) {
        // Failed to read the source file - that's ok.
    }
}
//# sourceMappingURL=internalReporter.js.map