/*---------------------------------------------------------
 * Copyright (C) Microsoft Corporation. All rights reserved.
 *--------------------------------------------------------*/
"use strict";
const fs = require("fs");
const utils = require("./utils");
var LogLevel;
(function (LogLevel) {
    LogLevel[LogLevel["Verbose"] = 0] = "Verbose";
    LogLevel[LogLevel["Log"] = 1] = "Log";
    LogLevel[LogLevel["Error"] = 2] = "Error";
})(LogLevel = exports.LogLevel || (exports.LogLevel = {}));
/** Logger singleton */
let _logger;
let _pendingLogQ = [];
function log(msg, forceLog = false, level = LogLevel.Log) {
    msg = msg + '\n';
    write(msg, forceLog, level);
}
exports.log = log;
function verbose(msg) {
    log(msg, undefined, LogLevel.Verbose);
}
exports.verbose = verbose;
function error(msg, forceLog = true) {
    log(msg, forceLog, LogLevel.Error);
}
exports.error = error;
/**
 * `log` adds a newline, this one doesn't
 */
function write(msg, forceLog = false, level = LogLevel.Log) {
    // [null, undefined] => string
    msg = msg + '';
    if (_pendingLogQ) {
        _pendingLogQ.push({ msg, level });
    }
    else {
        _logger.log(msg, level, forceLog);
    }
}
exports.write = write;
/**
 * Set the logger's minimum level to log. Log messages are queued before this is
 * called the first time, because minLogLevel defaults to Error.
 */
function setMinLogLevel(logLevel) {
    if (_logger) {
        _logger.minLogLevel = logLevel;
        // Clear out the queue of pending messages
        if (_pendingLogQ) {
            const logQ = _pendingLogQ;
            _pendingLogQ = null;
            logQ.forEach(item => write(item.msg, undefined, item.level));
        }
    }
}
exports.setMinLogLevel = setMinLogLevel;
function init(logCallback, logFilePath, logToConsole) {
    // Re-init, create new global Logger
    _pendingLogQ = [];
    _logger = new Logger(logCallback, logFilePath, logToConsole);
    if (logFilePath) {
        log(`Verbose logs are written to ${logFilePath}`);
        const d = new Date();
        const timestamp = d.toLocaleTimeString() + ', ' + d.toLocaleDateString();
        log(timestamp);
    }
}
exports.init = init;
/**
 * Manages logging, whether to console.log, file, or VS Code console.
 */
class Logger {
    get minLogLevel() { return this._minLogLevel; }
    set minLogLevel(logLevel) {
        this._minLogLevel = logLevel;
        // Open a log file in the specified location. Overwritten on each run.
        if (logLevel < LogLevel.Error && this._logFilePath) {
            this._logFileStream = fs.createWriteStream(this._logFilePath);
            this._logFileStream.on('error', e => {
                this.sendLog(`Error involving log file at path: ${this._logFilePath}. Error: ${e.toString()}`, LogLevel.Error);
            });
        }
    }
    constructor(logCallback, logFilePath, logToConsole) {
        this._logCallback = logCallback;
        this._logFilePath = logFilePath;
        this._logToConsole = logToConsole;
        this.minLogLevel = LogLevel.Error;
    }
    /**
     * @param forceLog - Writes to the diagnostic logging channel, even if diagnostic logging is not enabled.
     *      (For messages that appear whether logging is enabled or not.)
     */
    log(msg, level, forceLog) {
        if (level >= this.minLogLevel || forceLog) {
            this.sendLog(msg, level);
        }
        if (this._logToConsole) {
            const logFn = level === LogLevel.Error ? console.error : console.log;
            logFn(utils.trimLastNewline(msg));
        }
        // If an error, prepend with '[Error]'
        if (level === LogLevel.Error) {
            msg = `[${LogLevel[level]}] ${msg}`;
        }
        if (this._logFileStream) {
            this._logFileStream.write(msg);
        }
    }
    sendLog(msg, level) {
        // Truncate long messages, they can hang VS Code
        if (msg.length > 1500) {
            const endsInNewline = !!msg.match(/(\n|\r\n)$/);
            msg = msg.substr(0, 1500) + '[...]';
            if (endsInNewline) {
                msg = msg + '\n';
            }
        }
        if (this._logCallback) {
            this._logCallback(msg, level);
        }
    }
}

//# sourceMappingURL=logger.js.map
