"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var diffUtil = require("diff");
exports.hasFunctionName = function () {
    function foo() { }
    return foo.name === 'foo';
}();
function createDiff(actual, expected) {
    actual = toJSON(actual);
    expected = toJSON(expected);
    var diff = diffUtil
        .createPatch('', actual + '\n', expected + '\n', '', '')
        .split('\n')
        .slice(5, -1)
        .join('\n')
        .replace(/^@@[^@]*@@$/gm, '[...]');
    if (diff) {
        diff = diff.replace(/^([+-]?)(.*)$/gm, function (_, indicator, line) {
            if (line === '[...]') {
                return line;
            }
            return (indicator === '+' ? 'E' : indicator === '-' ? 'A' : '') + ' ' + line;
        });
    }
    return diff;
}
exports.createDiff = createDiff;
function getShouldWait(waitMode, message) {
    var shouldWait = false;
    var eventName = message.name;
    if (waitMode === 'fail') {
        if (eventName === 'testFail' ||
            eventName === 'suiteError' ||
            eventName === 'fatalError') {
            shouldWait = true;
        }
    }
    else if (waitMode === true) {
        shouldWait = true;
    }
    else if (Array.isArray(waitMode) && waitMode.indexOf(eventName) !== -1) {
        shouldWait = true;
    }
    return shouldWait;
}
exports.getShouldWait = getShouldWait;
function normalizePath(path) {
    if (path && path.length > 0 && path[path.length - 1] !== '/') {
        return path + "/";
    }
    return path;
}
exports.normalizePath = normalizePath;
function parseArgs(rawArgs) {
    var args = {};
    rawArgs.forEach(function (arg) {
        var _a = arg.split('=', 2), name = _a[0], value = _a[1];
        if (typeof value === 'undefined') {
            args[name] = true;
        }
        else {
            if (!(name in args)) {
                args[name] = value;
            }
            else if (!Array.isArray(args[name])) {
                args[name] = [args[name], value];
            }
            else {
                args[name].push(value);
            }
        }
    });
    return args;
}
exports.parseArgs = parseArgs;
function parseJSON(json) {
    return JSON.parse(removeComments(json));
}
exports.parseJSON = parseJSON;
function parseValue(name, value, parser) {
    if (typeof parser === 'string') {
        switch (parser) {
            case 'boolean':
                if (typeof value === 'boolean') {
                    return value;
                }
                if (value === 'true') {
                    return true;
                }
                if (value === 'false') {
                    return false;
                }
                throw new Error("Non-boolean value \"" + value + "\" for " + name);
            case 'number':
                var numValue = Number(value);
                if (!isNaN(numValue)) {
                    return numValue;
                }
                throw new Error("Non-numeric value \"" + value + "\" for " + name);
            case 'regexp':
                if (typeof value === 'string') {
                    return new RegExp(value);
                }
                if (value instanceof RegExp) {
                    return value;
                }
                throw new Error("Non-regexp value \"" + value + "\" for " + name);
            case 'object':
                if (typeof value === 'string') {
                    try {
                        return JSON.parse(value);
                    }
                    catch (error) {
                        throw new Error("Non-object value \"" + value + "\" for " + name);
                    }
                }
                if (typeof value === 'object') {
                    return value;
                }
                throw new Error("Non-object value \"" + value + "\" for " + name);
            case 'string':
                if (typeof value === 'string') {
                    return value;
                }
                throw new Error("Non-string value \"" + value + "\" for " + name);
            case 'string[]':
                if (!value) {
                    value = [];
                }
                if (typeof value === 'string') {
                    value = [value];
                }
                if (Array.isArray(value) && value.every(function (v) { return typeof v === 'string'; })) {
                    return value;
                }
                throw new Error("Non-string[] value \"" + value + "\" for " + name);
            case 'object|string':
                if (typeof value === 'string') {
                    if (value[0] === '{') {
                        try {
                            return JSON.parse(value);
                        }
                        catch (error) {
                            throw new Error("Invalid object string \"" + value + "\" for " + name);
                        }
                    }
                    return value;
                }
                if (typeof value === 'object') {
                    return value;
                }
                throw new Error("Non-string|object value \"" + value + "\" for " + name);
        }
    }
    else if (typeof parser === 'function') {
        return parser(value);
    }
    else {
        throw new Error('Parser must be a type name or a function');
    }
}
exports.parseValue = parseValue;
function pullFromArray(haystack, needle) {
    var removed = [];
    var i = 0;
    while ((i = haystack.indexOf(needle, i)) > -1) {
        removed.push(haystack.splice(i, 1)[0]);
    }
    return removed;
}
exports.pullFromArray = pullFromArray;
function retry(callback, numRetries) {
    var numAttempts = 0;
    return callback().catch(function retry(error) {
        if (error.name !== 'CancelError' && ++numAttempts <= numRetries) {
            return callback().catch(retry);
        }
        throw error;
    });
}
exports.retry = retry;
function toJSON(object) {
    return JSON.stringify(object, serializeReplacer, '  ');
}
exports.toJSON = toJSON;
function serializeReplacer(_key, value) {
    if (!value) {
        return value;
    }
    if (value instanceof RegExp) {
        return value.source;
    }
    if (typeof value === 'function') {
        return value.toString();
    }
    return value;
}
function removeComments(text) {
    var state = 'default';
    var i = 0;
    var chars = text.split('');
    while (i < chars.length) {
        switch (state) {
            case 'block-comment':
                if (chars[i] === '*' && chars[i + 1] === '/') {
                    chars[i] = ' ';
                    chars[i + 1] = ' ';
                    state = 'default';
                    i += 2;
                }
                else if (chars[i] !== '\n') {
                    chars[i] = ' ';
                    i += 1;
                }
                else {
                    i += 1;
                }
                break;
            case 'line-comment':
                if (chars[i] === '\n') {
                    state = 'default';
                }
                else {
                    chars[i] = ' ';
                }
                i += 1;
                break;
            case 'string':
                if (chars[i] === '"') {
                    state = 'default';
                    i += 1;
                }
                else if (chars[i] === '\\' && chars[i + 1] === '\\') {
                    i += 2;
                }
                else if (chars[i] === '\\' && chars[i + 1] === '"') {
                    i += 2;
                }
                else {
                    i += 1;
                }
                break;
            default:
                if (chars[i] === '"') {
                    state = 'string';
                    i += 1;
                }
                else if (chars[i] === '/' && chars[i + 1] === '*') {
                    chars[i] = ' ';
                    chars[i + 1] = ' ';
                    state = 'block-comment';
                    i += 2;
                }
                else if (chars[i] === '/' && chars[i + 1] === '/') {
                    chars[i] = ' ';
                    chars[i + 1] = ' ';
                    state = 'line-comment';
                    i += 2;
                }
                else {
                    i += 1;
                }
        }
    }
    return chars.join('');
}
//# sourceMappingURL=util.js.map