'use strict';

import * as vscode from 'vscode';
import { spawnSync } from 'child_process';
import {
    guessFidlFormatToolPath,
    getFidlFormatToolPathFromPreferences,
    FormatToolError,
    FormatToolErrorCause
} from './tool_finder';

const notDefined = "FIDL format tool not specified. Please set the path to fidl-format in Settings.";
const notExecutable = "FIDL format tool doesn't exist or can't be run. Please verify the path to fidl-format in Settings.";
const formatterError = "Error formatting FIDL";

const editSettingLabel = "Edit setting";

async function showError(e: FormatToolError) {
    let message;
    let showEdit = false;
    switch (e.cause) {
        case FormatToolErrorCause.ToolNotSpecified:
            message = notDefined;
            showEdit = true;
            break;
        case FormatToolErrorCause.ToolNotExecutable:
            message = notExecutable;
            showEdit = true;
            break;
        case FormatToolErrorCause.FormatterError:
            message = `${formatterError}: ${e.formatterMessage}`
            break;
        default:
            // This shouldn't happen. Since we don't know what kind of error we
            // have, we rethrow so this error appears in the console during
            // development.
            throw e;
    }
    let items: string[] = [];
    if (showEdit) {
        items.push(editSettingLabel);
    }
    let item = await vscode.window.showErrorMessage(message, ...items);
    switch (item) {
        case undefined:
        case null:
            // The user did not choose to edit setting.
            return;
        case editSettingLabel:
            vscode.commands.executeCommand('workbench.action.openSettings', 'fidl.formatTool');
    }
}

/**
 * A formatting edit provider that runs fidl-format over the code in the
 * current FIDL file.
 *
 * Objects of this class will check for the presence of the fidl-format path in
 * settings when instantiated and on every formatting request. If the path is
 * left empty (the default) and the path to fidl-format isn't specified,
 * objects of this class will show a notification to the user each time they
 * try to format a FIDL file.
 */
export default class FidlFormattingEditProvider implements vscode.DocumentFormattingEditProvider {
    /**
     * The cached path to the autodetected fidl-format tool. This is set once
     * for the session if the user hasn't explicitly set a path in preferences.
     */
    cachedGuessedFidlFormatToolPath: string | null = null;
    constructor() {
        if (getFidlFormatToolPathFromPreferences()) {
            // The fidl-format tool path is specified in preferences, so no
            // caching is needed.
            return;
        }

        guessFidlFormatToolPath().then(
            (p) => this.cachedGuessedFidlFormatToolPath = p,
            (e: FormatToolError) => showError(e));

    }

    async provideDocumentFormattingEdits(document: vscode.TextDocument): Promise<vscode.TextEdit[]> {
        const fromPrefs = getFidlFormatToolPathFromPreferences();
        let formatTool: string;

        if (fromPrefs) {
            // If the user has set a fidl-format path, that takes precedence.
            formatTool = fromPrefs;
            // Remove any cached (i.e. autodetected) tool.
            this.cachedGuessedFidlFormatToolPath = null;
        } else if (this.cachedGuessedFidlFormatToolPath) {
            // If there is a cached fidl-format path, use that for this
            // session.
            formatTool = this.cachedGuessedFidlFormatToolPath;
        } else {
            // Find the fidl-format tool.
            try {
                formatTool = await guessFidlFormatToolPath();
            } catch (e) {
                showError(e);
                return [];
            }
        }

        // FIDL files are assumed to always be UTF-8.
        const format = spawnSync(formatTool, [], { encoding: 'utf8', input: document.getText() });
        if (format.status) {
            // fidl-format exited with an error.
            const e = new FormatToolError(FormatToolErrorCause.FormatterError);
            e.formatterMessage = format.stderr;
            showError(e);
            // Return no edits. i.e. no changes to document.
            return [];
        }

        const fileStart = new vscode.Position(0, 0);
        const fileEnd = document.lineAt(document.lineCount - 1).range.end;

        // Casting: because spawnSync was called with an encoding,
        // format.stdout is already a string.
        return [new vscode.TextEdit(new vscode.Range(fileStart, fileEnd), format.stdout as string)];
    }
}
