"use strict";
var task_sequence_factories_1 = require("../task.sequence.factories");
var task_resolve_1 = require("../task.resolve");
var taskErrors = require("../task.errors");
var watchErrors = require("../watch.errors");
var path_1 = require("path");
var watch_resolve_1 = require("../watch.resolve");
var task_resolve_2 = require("../task.resolve");
var task_sequence_1 = require("../task.sequence");
var task_utils_1 = require("../task.utils");
var task_list_1 = require("./task.list");
var reports = require("../reporter.resolve");
var baseUrl = 'http://crossbow-cli.io/docs/errors';
var archy = require('archy');
var parsed = path_1.parse(__dirname);
var depsDir = path_1.join(path_1.dirname(parsed.dir), 'node_modules');
(function (LogLevel) {
    LogLevel[LogLevel["Short"] = 0] = "Short";
    LogLevel[LogLevel["Verbose"] = 1] = "Verbose";
})(exports.LogLevel || (exports.LogLevel = {}));
var LogLevel = exports.LogLevel;
function default_1(report, observer) {
    if (typeof exports.reporterFunctions[report.type] === 'function') {
        var outputFn = exports.reporterFunctions[report.type];
        var output = outputFn.call(null, report);
        if (typeof output === 'string') {
            if (output === '')
                return;
            observer.onNext({ origin: report.type, data: [output] });
        }
        else if (Array.isArray(output) && output.length) {
            observer.onNext({ origin: report.type, data: output });
        }
        else {
            console.log('STRING or ARRAY not returned for', report.type);
        }
    }
}
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = default_1;
exports.reporterFunctions = (_a = {},
    _a[reports.ReportTypes.UsingInputFile] = function (report) {
        return report.data.sources.map(function (input) {
            return "Using: {cyan.bold:" + input.relative + "}";
        }).join('\n');
    },
    _a[reports.ReportTypes.InputError] = function (report) {
        var lines = ["Sorry, there were errors resolving your input files"];
        var _a = report.data, sources = _a.sources, errors = _a.errors;
        /**
         * If the report has 'sources' it means it was an external file
         */
        if (sources.length) {
            sources.forEach(function (item) {
                lines.push("{red.bold:x " + item.rawInput + "}");
                lines.push.apply(lines, getExternalError(item.errors[0].type, item.errors[0], item).split('\n'));
            });
        }
        else {
            /**
             * Otherwise it was some other input error
             */
            errors.forEach(function (error) {
                lines.push.apply(lines, getExternalError(error.type, error).split('\n'));
            });
        }
        return lines;
    },
    _a[reports.ReportTypes.InvalidReporter] = function (report) {
        var lines = ["{red.bold:x} Sorry, there were problems resolving your reporters"];
        var reporters = report.data.reporters;
        reporters.invalid.forEach(function (reporter) {
            reporter.errors.forEach(function (err) {
                if (err.type === reports.ReporterErrorTypes.ReporterFileNotFound) {
                    lines.push("{red.bold:x " + err.file.resolved);
                }
                lines.push.apply(lines, getExternalError(err.type, err).split('\n'));
            });
        });
        return lines;
    },
    _a[reports.ReportTypes.DuplicateInputFile] = function (report) {
        var error = report.data.error;
        var lines = [
            "Sorry, this would cause an existing file to be overwritten",
            ("{red.bold:x " + error.file.rawInput + "}")
        ];
        return lines.concat(getExternalError(error.type, error, error.file).split('\n'));
    },
    _a[reports.ReportTypes.InputFileCreated] = function (report) {
        return ("{green:\u2714} Created file: {cyan.bold:" + report.data.parsed.base + "}\n \nNow, try the `{yellow:hello-world}` example in that file by running: \n \n  {gray:$} crossbow run {bold:hello-world} \n \nOr to see multiple tasks running, with some in parallel, try: \n\n  {gray:$} crossbow run {bold:all}").split('\n');
    },
    _a[reports.ReportTypes.InitInputFileTypeNotSupported] = function (report) {
        var error = report.data.error;
        return [
            ("Sorry, the type {cyan.bold:" + error.providedType + "} is not currently supported"),
            ("{red.bold:x '" + error.providedType + "'}")
        ].concat(getExternalError(error.type, error).split('\n'));
    },
    _a[reports.ReportTypes.SimpleTaskList] = function (report) {
        return [
            '{yellow:Available Tasks:'
        ].concat(report.data.lines);
    },
    _a[reports.ReportTypes.TaskTree] = function (report) {
        return reportTaskTree(report.data.tasks, report.data.config, report.data.title);
    },
    _a[reports.ReportTypes.TaskList] = function (report) {
        var _a = report.data, config = _a.config, sequence = _a.sequence, titlePrefix = _a.titlePrefix, cli = _a.cli;
        if (config.verbose === 1 /* Verbose */) {
            var cliInput = cli.input.slice(1).map(function (x) { return ("'" + x + "'"); }).join(' ');
            return reportSequenceTree(sequence, config, "+ Task Tree for " + cliInput);
        }
        else {
            return "{yellow:+}" + titlePrefix + " {bold:" + cli.input.slice(1).join(', ');
        }
    },
    _a[reports.ReportTypes.TaskErrors] = function (report) {
        var _a = report.data, taskCollection = _a.taskCollection, tasks = _a.tasks, config = _a.config;
        var lines = [
            '{gray.bold:------------------------------------------------}',
            '{err: } Sorry, there were errors resolving your tasks,',
            '  So none of them were run.',
            '{gray.bold:------------------------------------------------}',
        ];
        taskCollection.forEach(function (n, i) {
            lines.push.apply(lines, reportTaskTree([tasks[i]], config, "+ input: '" + n + "'"));
        });
        return lines;
    },
    _a[reports.ReportTypes.TaskReport] = function (report) {
        if (report.data.progress) {
            return task_list_1._taskReport(report.data.report);
        }
        return '';
    },
    _a[reports.ReportTypes.DocsInvalidTasksSimple] = function () {
        return [
            '{red.bold:x Invalid tasks',
            'Sorry, we cannot generate documentation for you right now',
            'as you have invalid tasks. Please run {bold:$ crossbow tasks} to see',
            'details about these errors',
        ];
    },
    _a[reports.ReportTypes.NoTasksAvailable] = function () {
        return [
            'Sorry, there were no tasks available.',
            "{red.bold:x Input: ''}"
        ].concat(getExternalErrorLines(task_utils_1.InputErrorTypes.NoTasksAvailable, {}));
    },
    _a[reports.ReportTypes.NoTasksProvided] = function () {
        return "Entering interactive mode as you didn't provide a task to run";
    },
    _a[reports.ReportTypes.BeforeWatchTaskErrors] = function (report) {
        var lines = [
            '{err: } Sorry, there were errors resolving your {red:`before`} tasks',
            '  So none of them were run, and no watchers have begun either.',
        ];
        var _a = report.data, watchTasks = _a.watchTasks, trigger = _a.trigger;
        watchTasks.all.forEach(function (watchTask) {
            var cliInput = watch_resolve_1.resolveBeforeTasks(trigger.config.before, trigger.input, [watchTask]);
            var tasks = task_resolve_2.resolveTasks(cliInput, trigger);
            if (!tasks.all.length) {
                return;
            }
            if (trigger.config.verbose === 1 /* Verbose */) {
                lines.push.apply(lines, reportTaskTree(tasks.all, trigger.config, "+ Tasks to run before: '" + watchTask.name + "'"));
            }
            if (tasks.invalid.length) {
                lines.push.apply(lines, reportTaskTree(tasks.all, trigger.config, "+ Tasks to run before: '" + watchTask.name + "'"));
            }
        });
        return lines;
    },
    _a[reports.ReportTypes.BeforeTaskList] = function (report) {
        var _a = report.data, config = _a.config, cli = _a.cli, sequence = _a.sequence;
        var lines = [
            ("{yellow:+} Before tasks for watcher: {bold:" + cli.input.join(', ') + "}"),
        ];
        if (config.verbose === 1 /* Verbose */) {
            var cliInput = cli.input.map(function (x) { return ("'" + x + "'"); }).join(' ');
            lines.push(reportSequenceTree(sequence, config, "+ Task Tree for " + cliInput));
        }
        return lines;
    },
    _a[reports.ReportTypes.BeforeTasksDidNotComplete] = function (report) {
        return [
            ("{red:x} " + report.data.error.message),
            '  so none of the watchers started',
        ];
    },
    _a[reports.ReportTypes.WatchTaskTasksErrors] = function (report) {
        var _a = report.data, runner = _a.runner, config = _a.config, tasks = _a.tasks;
        if (runner._tasks.invalid.length) {
            return [
                '{gray.bold:---------------------------------------------------}',
                "{err: } Sorry, there were errors when resolving the tasks",
                "  that will be used in the following watcher"
            ].concat(logWatcher(runner), reportTaskTree(tasks, config, "+ input: " + runner.parent));
        }
        var lines = [
            '{gray.bold:---------------------------------------------------}',
            "{ok: } No errors from"
        ].concat(logWatcher(runner));
        if (config.verbose === 1 /* Verbose */) {
            lines.push.apply(lines, reportTaskTree(tasks, config, "+ input: " + runner.parent));
        }
        return lines;
    },
    _a[reports.ReportTypes.WatchTaskErrors] = function (report) {
        var watchTasks = report.data.watchTasks;
        var errorCount = watchTasks.reduce(function (acc, item) {
            return acc + item.errors.length;
        }, 0);
        var lines = ["Sorry, there were errors resolving your watch tasks"];
        watchTasks.forEach(function (task) {
            if (task.errors.length) {
                lines.push("{red.bold:x '" + task.name + "'}");
                lines.push.apply(lines, getWatchError(task.errors[0], task).split('\n'));
            }
            else {
                lines.push("{ok: } '" + task.name + "'}");
            }
        });
        lines.push(errorSummary(errorCount));
        return lines;
    },
    _a[reports.ReportTypes.WatchTaskReport] = function (report) {
        return task_list_1._taskReport(report.data.report);
    },
    _a[reports.ReportTypes.NoWatchersAvailable] = function () {
        return [
            'Sorry, there were no watchers available to run',
            "{red.bold:x No watchers available}"
        ].concat(getExternalError(task_utils_1.InputErrorTypes.NoWatchersAvailable, {}).split('\n'));
    },
    _a[reports.ReportTypes.NoWatchTasksProvided] = function () {
        return "Entering interactive mode as you didn't provide a watcher to run";
    },
    _a[reports.ReportTypes.Watchers] = function (report) {
        var lines = [];
        lines.push("");
        report.data.watchTasks.forEach(function (watchTask) {
            watchTask.watchers.forEach(function (watcher) {
                lines.push("{bold:'" + watcher.patterns.map(function (x) { return task_utils_1._e(x); }).join(', ') + "}'");
                lines.push(" {yellow:->} " + watcher.tasks.join(', '));
            });
            lines.push("");
        });
        lines.push('Watching for changes...');
        return lines;
    },
    _a[reports.ReportTypes.WatcherNames] = function (report) {
        var runners = report.data.runners;
        var lines = ['{yellow:Available Watchers:}'];
        runners.valid.forEach(function (runner) {
            lines.push('');
            lines.push("    {bold:Name}:     " + runner.parent);
            lines.push("    {bold:Patterns}: " + runner.patterns.map(task_utils_1._e).join(', '));
            lines.push("    {bold:Tasks}:    " + runner.tasks.join(', '));
        });
        lines.push("");
        lines.push("Run your watchers in the following way:");
        lines.push("");
        runners.valid.forEach(function (runner) {
            lines.push("    {gray:$} crossbow watch {bold:" + runner.parent + "}");
        });
        if (runners.valid.length > 1) {
            lines.push('');
            lines.push('Or run multiple watchers at once, such as:');
            lines.push("");
            lines.push('    {gray:$} crossbow watch ' + runners.valid.slice(0, 2).map(function (x) { return ("{bold:" + x.parent + "}"); }).join(' '));
            lines.push('');
        }
        return lines;
    },
    _a[reports.ReportTypes.NoFilesMatched] = function (report) {
        var watcher = report.data.watcher;
        return "{red:x warning} {cyan:" + watcher.patterns.join(' ') + "} did not match any files";
    },
    _a[reports.ReportTypes.WatcherTriggeredTasks] = function (report) {
        var _a = report.data, index = _a.index, taskCollection = _a.taskCollection;
        return "{yellow:+} [" + index + "] " + getTaskCollectionList(taskCollection).join(', ');
    },
    _a[reports.ReportTypes.WatcherTriggeredTasksCompleted] = function (report) {
        var _a = report.data, index = _a.index, taskCollection = _a.taskCollection, time = _a.time;
        return "{green:\u2714} [" + index + "] " + getTaskCollectionList(taskCollection).join(', ') + " {yellow:(" + task_list_1.duration(time) + ")}";
    },
    _a[reports.ReportTypes.DocsGenerated] = function () {
        /** noop **/
    },
    _a[reports.ReportTypes.DocsInputFileNotFound] = function (report) {
        var error = report.data.error;
        return [
            "Sorry, there were errors resolving your input files",
            ("{red.bold:x '" + error.file.resolved + "'}")
        ].concat(getExternalError(error.type, error).split('\n'));
    },
    _a[reports.ReportTypes.DocsAddedToFile] = function (report) {
        var file = report.data.file;
        return "{green:\u2714} Docs added to: {cyan.bold:" + file.relative + "}";
    },
    _a[reports.ReportTypes.DocsOutputFileExists] = function (report) {
        var error = report.data.error;
        return [
            ("{red.bold:x '" + error.file.resolved + "'}")
        ].concat(getExternalError(error.type, error).split('\n'));
    },
    _a[reports.ReportTypes.SignalReceived] = function reportSummary(report) {
        return ["", ("{yellow:~~~} Exit Signal Received {cyan:(code: " + report.data.code + ")} {yellow:~~~}")];
    },
    _a[reports.ReportTypes.BeforeTasksSummary] = function reportSummary(report) {
        var _a = report.data, sequence = _a.sequence, config = _a.config, runtime = _a.runtime;
        var runnableTasks = task_sequence_1.collectRunnableTasks(sequence, []);
        var errorTasks = runnableTasks.filter(function (x) { return x.stats.errors.length > 0; });
        var lines = [];
        // todo - show a reduced tree showing only errors
        if (config.verbose === 1 /* Verbose */ || errorTasks.length > 0) {
            lines.push(reportSequenceTree(sequence, config, "+ Results from before tasks", true));
        }
        else {
            lines.push("{ok: } Before tasks completed {yellow:(" + task_list_1.duration(runtime) + ")}");
        }
        if (errorTasks.length) {
            lines.push("{red:x} " + errorTasks.length + " error(s) from before tasks");
        }
        return lines;
    },
    _a[reports.ReportTypes.WatcherSummary] = function reportSummary(report) {
        var _a = report.data, sequence = _a.sequence, config = _a.config, watcher = _a.watcher;
        var runnableTasks = task_sequence_1.collectRunnableTasks(sequence, []);
        var errorTasks = runnableTasks.filter(function (x) { return x.stats.errors.length > 0; });
        var lines = [];
        // todo - show a reduced tree showing only errors
        if (config.verbose === 1 /* Verbose */ || errorTasks.length > 0) {
            lines.push(reportSequenceTree(sequence, config, "+ Results from " + watcher.parent, true));
        }
        if (errorTasks.length) {
            lines.push("{red:x} " + errorTasks.length + " error(s) from watcher {yellow:" + watcher.parent + "}");
        }
        return lines;
    },
    _a[reports.ReportTypes.Summary] = function reportSummary(report) {
        var _a = report.data, sequence = _a.sequence, cli = _a.cli, config = _a.config, runtime = _a.runtime;
        var runnableTasks = task_sequence_1.collectRunnableTasks(sequence, []);
        var errorTasks = runnableTasks.filter(function (x) { return x.stats.errors.length > 0; });
        var skippedTasks = runnableTasks.filter(function (x) { return x.stats.skipped; });
        var completedTasks = runnableTasks.filter(function (x) { return x.stats.completed && !x.stats.skipped; });
        var lines = [];
        // todo - show a reduced tree showing only errors
        if (config.verbose === 1 /* Verbose */ || errorTasks.length > 0) {
            var cliInput = cli.input.slice(1).map(function (x) { return ("'" + x + "'"); }).join(' ');
            lines.push(reportSequenceTree(sequence, config, "+ Results from " + cliInput, true));
        }
        lines.push("");
        if (errorTasks.length > 0) {
            lines.push("{red:x} {bold:Summary:}");
        }
        else {
            lines.push("{ok: } {bold:Summary:}");
        }
        lines.push("");
        lines.push("    Total Time: {yellow:" + task_list_1.duration(runtime) + "}");
        lines.push("    Tasks:      {cyan:" + runnableTasks.length + "}");
        if (skippedTasks.length) {
            lines.push("    Skipped:    {cyan:" + skippedTasks.length + "}");
        }
        if (errorTasks.length > 0) {
            lines.push("    Failed:     {red:" + errorTasks.length + "}");
        }
        lines.push("    Completed:  {green:" + completedTasks.length + "}");
        lines.push('');
        return lines;
    },
    _a[reports.ReportTypes.HashDirError] = function (report) {
        var _a = report.data, error = _a.error, cwd = _a.cwd;
        return [
            "{red.bold:x CB-History hash failed} (tasks will still run)"
        ].concat(getExternalError(error.type, error, cwd).split('\n'));
    },
    _a
);
/**
 * There are multiple ways to output trees to the screen,
 * so this helper function helps to normalize the output
 * by providing the same padding on all but the first line.
 */
function multiLineTree(tree) {
    var lines = [];
    var split = tree.split('\n');
    lines.push(split[0]);
    split.slice(1, -1).forEach(function (line) {
        lines.push("   " + line);
    });
    return lines.join('\n');
}
exports.multiLineTree = multiLineTree;
function getTaskCollectionList(taskCollection) {
    return taskCollection.map(incomingTaskItemAsString);
}
function incomingTaskItemAsString(x) {
    if (typeof x === 'string') {
        return task_utils_1._e(x);
    }
    if (typeof x === 'function') {
        var fn = x;
        if (fn.name) {
            return "[Function: " + fn.name + "]";
        }
        return '[Function]';
    }
}
function getWatcherNode(watcher) {
    var tasksString = (function () {
        return watcher.tasks.map(incomingTaskItemAsString).join(', ');
    })();
    return [
        ("{bold:Patterns:} {cyan:" + watcher.patterns.map(function (x) { return task_utils_1._e(x); }).join(', ') + "}"),
        ("{bold:Tasks:} {cyan:" + tasksString + "}"),
    ].join('\n');
}
function logWatcher(runner) {
    return [
        ("  {bold:Watcher name:} {cyan:" + runner.parent + "}"),
        ("      {bold:Patterns:} {cyan:" + runner.patterns.join(', ') + "}"),
        ("         {bold:Tasks:} {cyan:" + runner.tasks.join(', ') + "}"),
    ];
}
function errorSummary(errorCount) {
    if (errorCount) {
        var plural = errorCount === 1 ? 'error' : 'errors';
        return "{red:x} " + errorCount + " " + plural + " found (see above)";
    }
    else {
        return "{ok: } 0 errors found";
    }
}
function getErrorText(sequenceLabel, stats, err, config) {
    if (!err.stack) {
        return err.toString();
    }
    /**
     * If _cbError is on the error object, it's a crossbow-generated
     * error so we handle it as though we know what we're doing
     */
    if (err._cbError) {
        return [
            ("{red.bold:x} {red:" + sequenceLabel + "} {yellow:(" + task_list_1.duration(stats.duration) + ")}"),
            task_utils_1.__e(err.stack)
        ].join('\n');
    }
    /**
     * At this point we have no idea what type the error is, so
     * the following code just makes the first line red and then
     * processes the stack traces (to remove internals)
     */
    var head = [
        ("{red.bold:x} " + sequenceLabel + " {yellow:(" + task_list_1.duration(stats.duration) + ")}"),
        ("{red.bold:" + err.stack.split('\n').slice(0, 1) + "}")
    ];
    var body = err.stack.split('\n').slice(1);
    var stack = getStack(body, config);
    var tail = "- Please see above for any output that may of occurred";
    if (!stack) {
        return head.concat([tail]).join('\n');
    }
    return head.concat(stack, [tail]).join('\n');
}
function getStack(stack, config) {
    /**
     * An array of string that can be compared
     * against each line of the stack trace to determine
     * if that line should be stipped. EG: we
     * don't want to muddy up stack traces with internals
     * from Rx/Immutable etc.
     */
    var stringMatches = (function () {
        if (config.debug)
            return [];
        return [
            parsed.dir,
            depsDir,
            'at bound (domain.js',
            'at runBound (domain.js'
        ];
    })();
    return stack
        .filter(function (line) {
        return stringMatches.every(function (string) {
            return line.indexOf(string) === -1;
        });
    });
}
exports.getStack = getStack;
/**
 * Add meta info to a sequence item suing the stats.
 * eg:
 *   @npm webpack -w
 * ->
 *   ✔ @npm webpack -w (14.2s)
 */
function appendStatsToSequenceLabel(label, stats, config) {
    /**
     * If any errors occured, append the error to the
     * label so it shows in the correct part of the tree
     */
    if (stats.errors.length) {
        var err = stats.errors[0];
        return getErrorText(label, stats, err, config);
    }
    /**
     * If this item was skipped, there cannot be anything to append
     */
    if (stats.skipped) {
        return "{yellow:-} " + label + " {yellow:(skipped)}";
    }
    /**
     * the item did not start if `started` is falsey
     */
    if (!stats.started) {
        return "{yellow:x} " + label + " {yellow:(didn't start)}";
    }
    /**
     * 'completed' means this task emitted a completion report.
     */
    if (stats.completed) {
        return "{green:\u2714} " + label + (" {yellow:(" + task_list_1.duration(stats.duration) + ")}");
    }
    /**
     * At this point, the task DID start, but the completed
     * flag is absent so we assume it was halted mid-flight.
     */
    return "{yellow:x} " + label + (" {yellow:(didn't complete, " + task_list_1.duration(stats.duration) + ")}");
}
/**
 * Show a tree of function calls
 */
function reportSequenceTree(sequence, config, title, showStats) {
    if (showStats === void 0) { showStats = false; }
    var toLog = getItems(sequence, []);
    var o = archy({ label: "{yellow:" + title + "}", nodes: toLog });
    return multiLineTree(o);
    function getItems(items, initial) {
        return items.reduce(function (acc, item) {
            var label = getSequenceLabel(item, config);
            var stats = item.stats;
            if (showStats && item.type === task_sequence_factories_1.SequenceItemTypes.Task) {
                label = appendStatsToSequenceLabel(label, item.stats, config);
            }
            var nodes = getItems(item.items, []);
            return acc.concat({
                label: label,
                nodes: nodes
            });
        }, initial);
    }
}
exports.reportSequenceTree = reportSequenceTree;
function getSequenceLabel(item, config) {
    /**
     * Get the sequence label for a runnable task
     */
    if (item.type === task_sequence_factories_1.SequenceItemTypes.Task) {
        var baseName_1 = (function () {
            // if (item.viaName) {
            //     return `${item.task.taskName} via {bold:${item.viaName}}`;
            // }
            if (item.subTaskName) {
                if (item.fnName) {
                    return item.task.taskName + " [Function: {bold:" + item.fnName + "}] with config {bold:" + item.subTaskName + "}";
                }
                else {
                    return item.task.taskName + " with config {bold:" + item.subTaskName + "}";
                }
            }
            if (item.task.type === task_resolve_1.TaskTypes.InlineFunction) {
                return item.task.rawInput + " " + task_utils_1.getFunctionName(item.task.inlineFunctions[0]);
            }
            if (item.task.type === task_resolve_1.TaskTypes.ExternalTask) {
                return "" + item.task.rawInput;
            }
            if (item.task.type === task_resolve_1.TaskTypes.Adaptor) {
                return "" + item.task.rawInput;
            }
            if (item.task.externalTasks.length) {
                return moduleLabel(item.task);
            }
            return item.task.taskName;
        })();
        return baseName_1;
    }
    var baseName = (function () {
        /**
         * Here we are dealing with a ParallelGroup or a SeriesGroup
         */
        if (item.items.length === 1) {
            /**
             * Don't append 'series' or 'parallel' if this group
             * only consists of 1 item
             */
            if (item.subTaskName) {
                return "{bold:" + item.taskName + ":" + item.subTaskName + "}";
            }
            return "{bold:" + item.taskName + "}";
        }
        var typeLabel = (function () {
            if (item.type === task_sequence_factories_1.SequenceItemTypes.ParallelGroup) {
                return '<parallel>';
            }
            return '<series>';
        })();
        return "{bold:" + item.taskName + "} " + typeLabel;
    })();
    if (item.skipped) {
        baseName += ' {yellow:(skipped)}';
    }
    if (item.stats && item.stats.skipped) {
        baseName += ' {yellow:(skipped)}';
    }
    return baseName;
}
function reportTaskTree(tasks, config, title) {
    var errorCount = 0;
    var toLog = getTasks(tasks, [], 0);
    var archy = require('archy');
    var output = archy({ label: "{yellow:" + title + "}", nodes: toLog });
    return multiLineTree(output).split('\n').concat([
        errorSummary(errorCount)
    ]);
    function getTasks(tasks, initial, depth) {
        return tasks.reduce(function (acc, task) {
            var errors = getErrors(task);
            if (errors.length) {
                errorCount += errors.length;
            }
            /**
             * Never show internal tasks at top-level
             */
            if (depth === 0) {
                if (task_utils_1.isInternal(task.rawInput)) {
                    return acc;
                }
            }
            var nodes = getTasks(task.tasks, [], depth++);
            var label = [getLabel(task)].concat(errors).join('\n');
            if (config.verbose === 1 /* Verbose */) {
                return acc.concat({
                    label: label,
                    nodes: nodes
                });
            }
            if (task.type === task_resolve_1.TaskTypes.Adaptor ||
                task.type === task_resolve_1.TaskTypes.ExternalTask) {
                if (task.errors.length) {
                    return acc.concat({
                        label: label,
                        nodes: []
                    });
                }
                return acc;
            }
            return acc.concat({
                label: label,
                nodes: nodes
            });
        }, initial);
    }
}
exports.reportTaskTree = reportTaskTree;
function getErrors(task) {
    if (!task.errors.length) {
        return [];
    }
    if (task.errors[0].type === taskErrors.TaskErrorTypes.TaskNotFound) {
        return [getSingleError(task.errors[0], task)];
    }
    return task.errors.map(function (error) { return getSingleError(error, task); });
}
exports.getErrors = getErrors;
function getSingleError(error, task) {
    return getExternalError(taskErrors.TaskErrorTypes[error.type], error, task);
}
function getWatchError(error, task) {
    return getExternalError(watchErrors.WatchTaskErrorTypes[error.type], error, task);
}
function getExternalError(type, error, val2) {
    return [
        ("{red:-} {bold:Error Type:}  " + type)
    ].concat(require('./error.' + type).apply(null, [error, val2]), [
        ("{red:-} {bold:Documentation}: {underline:" + baseUrl + "/{bold.underline:" + type + "}}"),
    ]).join('\n');
}
function getExternalErrorLines(type, error, val2) {
    return [
        ("{red:-} {bold:Error Type:}  " + type)
    ].concat(require('./error.' + type).apply(null, [error, val2]), [
        ("{red:-} {bold:Documentation}: {underline:" + baseUrl + "/{bold.underline:" + type + "}}"),
    ]);
}
function moduleLabel(task) {
    var filepath = path_1.relative(process.cwd(), task.externalTasks[0].rawInput);
    if (task.taskName === filepath) {
        return "" + task.taskName;
    }
    return task.taskName + " " + filepath;
}
function npmScriptLabel(task) {
    return "{magenta:[npm script]} " + task.command;
}
function getLabel(task) {
    if (task.type === task_resolve_1.TaskTypes.InlineFunction) {
        var fnName = (function () {
            if (task.inlineFunctions[0].name !== '') {
                return "[Function: " + task.inlineFunctions[0].name + "]";
            }
            return "[Function: " + task.taskName + "]";
        })();
        return maybeErrorLabel(task, fnName);
    }
    if (task.origin === task_resolve_1.TaskOriginTypes.NpmScripts) {
        return npmScriptLabel(task);
    }
    if (task.type === task_resolve_1.TaskTypes.TaskGroup) {
        if (task.errors.length) {
            return "{red.bold:x " + task.taskName + "}";
        }
        return "{bold:" + task.taskName + "}";
    }
    if (task.type === task_resolve_1.TaskTypes.ExternalTask) {
        return maybeErrorLabel(task, task.taskName);
    }
    if (task.type === task_resolve_1.TaskTypes.Adaptor) {
        return maybeErrorLabel(task, task.rawInput);
    }
    if (task.errors.length) {
        return "{red.bold:x " + task.taskName + "}";
    }
    return task.taskName + "}";
}
exports.getLabel = getLabel;
function maybeErrorLabel(task, label) {
    if (task.errors.length) {
        return "{red.bold:x " + label + "}";
    }
    return label;
}
var _a;
//# sourceMappingURL=defaultReporter.js.map