// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for details.

/**
 * Formatter for the Output channel.
 */

import { ILogger } from "../common/log/loggers";
import { LogHelper, LogLevel } from "../common/log/logHelper";
import { SettingsHelper } from "./settingsHelper";
import { OutputChannel } from "vscode";
import * as vscode from "vscode";

export class OutputChannelLogger implements ILogger {
    private outputChannel: OutputChannel;

    constructor(outputChannel: OutputChannel) {
        this.outputChannel = outputChannel;
        this.outputChannel.show();
    }

    public logInternalMessage(logLevel: LogLevel, message: string) {
        if (SettingsHelper.getShowInternalLogs()) {
            this.logMessage(this.getFormattedInternalMessage(logLevel, message));
            return;
        }
        console.log(this.getFormattedInternalMessage(logLevel, message));
    }

    public logMessage(message: string, formatMessage: boolean = true) {
        this.outputChannel.appendLine(formatMessage ?
            this.getFormattedMessage(message) :
            message);
    }

    public logError(errorMessage: string, error?: any, logStack: boolean = true) {
        this.logMessage(errorMessage, /* formatMessage */ false);
    }

    public logStreamData(data: Buffer, stream: NodeJS.WritableStream) {
        this.outputChannel.append(data.toString());
    }

    public logString(data: string) {
        this.outputChannel.append(data);
    }

    public setFocusOnLogChannel() {
        this.outputChannel.show();
    }

    public getOutputChannel(): OutputChannel {
        return this.outputChannel;
    }

    private getFormattedMessage(message: string) {
        return `######### ${message} ##########`;
    }

    private getFormattedInternalMessage(logLevel: LogLevel, message: string) {
        return (`${LogHelper.INTERNAL_TAG} [${LogLevel[logLevel]}] ${message}`);
    }
}

export class DelayedOutputChannelLogger implements ILogger {
    private outputChannelLogger: OutputChannelLogger;

    constructor(private channelName: string) { }

    public logInternalMessage(logLevel: LogLevel, message: string) {
        this.logger.logInternalMessage(logLevel, message);
    }

    public logMessage(message: string, formatMessage: boolean = true) {
        this.logger.logMessage(message, formatMessage);
    }

    public logError(errorMessage: string, error?: any, logStack: boolean = true) {
        this.logger.logError(errorMessage, error, logStack);
    }

    public logStreamData(data: Buffer, stream: NodeJS.WritableStream) {
        this.logger.logStreamData(data, stream);
    }

    public logString(data: string) {
        this.logger.logString(data);
    }

    public setFocusOnLogChannel() {
        this.logger.setFocusOnLogChannel();
    }

    private get logger(): OutputChannelLogger {
        if (!this.outputChannelLogger) {
            this.outputChannelLogger = new OutputChannelLogger(vscode.window.createOutputChannel(this.channelName));
        }
        return this.outputChannelLogger;
    }
}
