"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
var charm = require("charm");
var nodeUtil = require("util");
var Collector = require("istanbul/lib/collector");
var TextSummaryReport = require("istanbul/lib/report/text-summary");
var TextReport = require("istanbul/lib/report/text");
var Reporter_1 = require("./Reporter");
var Coverage_1 = require("./Coverage");
var LIGHT_RED = '\x1b[91m';
var LIGHT_GREEN = '\x1b[92m';
var LIGHT_YELLOW = '\x1b[93m';
var LIGHT_MAGENTA = '\x1b[95m';
var eventHandler = Reporter_1.createEventHandler();
var Runner = (function (_super) {
    __extends(Runner, _super);
    function Runner(executor, config) {
        if (config === void 0) { config = {}; }
        var _this = _super.call(this, executor, config) || this;
        _this.sessions = {};
        _this.hasErrors = false;
        _this.serveOnly = executor.config.serveOnly;
        _this._summaryReporter = new TextSummaryReport({
            watermarks: _this.watermarks
        });
        _this._detailedReporter = new TextReport({
            watermarks: _this.watermarks
        });
        _this.charm = charm();
        _this.charm.pipe(_this.output);
        _this.charm.display('reset');
        return _this;
    }
    Runner.prototype.coverage = function (message) {
        if (message.sessionId) {
            var session = this.sessions[message.sessionId || ''];
            session.coverage = session.coverage || new Collector();
            session.coverage.add(message.coverage);
        }
    };
    Runner.prototype.deprecated = function (message) {
        this.charm
            .write(LIGHT_YELLOW)
            .write('⚠︎ ' + message.original + ' is deprecated. ');
        if (message.replacement) {
            this.charm.write('Use ' + message.replacement + ' instead.');
        }
        else {
            this.charm.write('Please open a ticket at https://github.com/theintern/intern/issues if you still ' +
                'require access to this function.');
        }
        if (message.message) {
            this.charm.write(' ' + message.message);
        }
        this.charm.write('\n').display('reset');
    };
    Runner.prototype.error = function (error) {
        this.charm
            .foreground('red')
            .write('(ノಠ益ಠ)ノ彡┻━┻\n')
            .write(this.formatter.format(error))
            .display('reset')
            .write('\n');
        this.hasErrors = true;
    };
    Runner.prototype.log = function (message) {
        message.split('\n').forEach(function (line) {
            console.log("DEBUG: " + line);
        });
    };
    Runner.prototype.runEnd = function () {
        var _this = this;
        var collector = new Collector();
        var numTests = 0;
        var numFailedTests = 0;
        var numSkippedTests = 0;
        var sessionIds = Object.keys(this.sessions);
        var numEnvironments = sessionIds.length;
        sessionIds.forEach(function (sessionId) {
            var session = _this.sessions[sessionId];
            if (session.coverage) {
                var finalCoverage = session.coverage.getFinalCoverage();
                collector.add(finalCoverage);
            }
            numTests += session.suite.numTests;
            numFailedTests += session.suite.numFailedTests;
            numSkippedTests += session.suite.numSkippedTests;
        });
        this.charm.write('\n');
        if (collector.files().length > 0) {
            this._detailedReporter.writeReport(collector);
        }
        var message = 'TOTAL: tested %d platforms, %d/%d tests failed';
        if (numSkippedTests) {
            message += ' (' + numSkippedTests + ' skipped)';
        }
        if (this.hasErrors && !numFailedTests) {
            message += '; fatal error occurred';
        }
        this.charm
            .display('bright')
            .foreground(numFailedTests > 0 || this.hasErrors ? 'red' : 'green')
            .write(nodeUtil.format(message, numEnvironments, numFailedTests, numTests))
            .display('reset')
            .write('\n');
    };
    Runner.prototype.serverStart = function (server) {
        var message = "Listening on localhost:" + server.port;
        if (server.socketPort) {
            message += " (ws " + server.socketPort + ")";
        }
        this.charm.write(message + "\n");
    };
    Runner.prototype.suiteEnd = function (suite) {
        if (suite.error) {
            var error = suite.error;
            this.charm
                .foreground('red')
                .write('Suite ' + suite.id + ' FAILED\n')
                .write(this.formatter.format(error))
                .display('reset')
                .write('\n');
            this.hasErrors = true;
        }
        else if (!suite.hasParent) {
            if (!suite.sessionId) {
                return;
            }
            if (!this.sessions[suite.sessionId]) {
                if (!this.serveOnly) {
                    this.charm
                        .write(LIGHT_YELLOW)
                        .write('BUG: suiteEnd was received for invalid session ' + suite.sessionId)
                        .display('reset')
                        .write('\n');
                }
                return;
            }
            var session = this.sessions[suite.sessionId];
            if (session.coverage) {
                this._summaryReporter.writeReport(session.coverage);
            }
            else {
                this.charm
                    .write('No unit test coverage for ' + suite.name)
                    .display('reset')
                    .write('\n');
            }
            var name_1 = suite.name;
            var hasError = (function hasError(suite) {
                return suite.tests ? (suite.error || suite.tests.some(hasError)) : false;
            })(suite);
            var numFailedTests = suite.numFailedTests;
            var numTests = suite.numTests;
            var numSkippedTests = suite.numSkippedTests;
            var summary = nodeUtil.format('%s: %d/%d tests failed', name_1, numFailedTests, numTests);
            if (numSkippedTests) {
                summary += ' (' + numSkippedTests + ' skipped)';
            }
            if (hasError) {
                summary += '; fatal error occurred';
            }
            this.charm
                .write(numFailedTests || hasError > 0 ? LIGHT_RED : LIGHT_GREEN)
                .write(summary)
                .display('reset')
                .write('\n\n');
        }
    };
    Runner.prototype.suiteStart = function (suite) {
        if (!suite.hasParent) {
            this.sessions[suite.sessionId || ''] = { suite: suite };
            if (suite.sessionId) {
                this.charm.write('‣ Created session ' + suite.name + ' (' + suite.sessionId + ')\n');
            }
        }
    };
    Runner.prototype.testEnd = function (test) {
        if (test.error) {
            this.charm
                .write(LIGHT_RED)
                .write('× ' + test.id)
                .write(' (' + (test.timeElapsed / 1000) + 's)')
                .write('\n')
                .foreground('red')
                .write(this.formatter.format(test.error))
                .display('reset')
                .write('\n');
        }
        else if (test.skipped) {
            this.charm
                .write(LIGHT_MAGENTA)
                .write('~ ' + test.id)
                .foreground('white')
                .write(' (' + (test.skipped || 'skipped') + ')')
                .display('reset')
                .write('\n');
        }
        else {
            this.charm
                .write(LIGHT_GREEN)
                .write('✓ ' + test.id)
                .foreground('white')
                .write(' (' + (test.timeElapsed / 1000) + 's)')
                .display('reset')
                .write('\n');
        }
    };
    Runner.prototype.tunnelDownloadProgress = function (message) {
        this.charm.write('Tunnel download: ' + (message.progress.received / message.progress.total * 100).toFixed(3) + '%\r');
    };
    Runner.prototype.tunnelStart = function () {
        this.charm.write('Tunnel started\n');
    };
    Runner.prototype.tunnelStatus = function (message) {
        this.charm.write(message.status + '\x1b[K\r');
    };
    return Runner;
}(Coverage_1.default));
__decorate([
    eventHandler()
], Runner.prototype, "coverage", null);
__decorate([
    eventHandler()
], Runner.prototype, "deprecated", null);
__decorate([
    eventHandler()
], Runner.prototype, "error", null);
__decorate([
    eventHandler()
], Runner.prototype, "log", null);
__decorate([
    eventHandler()
], Runner.prototype, "runEnd", null);
__decorate([
    eventHandler()
], Runner.prototype, "serverStart", null);
__decorate([
    eventHandler()
], Runner.prototype, "suiteEnd", null);
__decorate([
    eventHandler()
], Runner.prototype, "suiteStart", null);
__decorate([
    eventHandler()
], Runner.prototype, "testEnd", null);
__decorate([
    eventHandler()
], Runner.prototype, "tunnelDownloadProgress", null);
__decorate([
    eventHandler()
], Runner.prototype, "tunnelStart", null);
__decorate([
    eventHandler()
], Runner.prototype, "tunnelStatus", null);
exports.default = Runner;
//# sourceMappingURL=Runner.js.map