import * as vscode from 'vscode';
import * as path from 'path';
import * as fs from 'fs';

export enum FormatToolErrorCause {
    ToolNotSpecified, ToolNotExecutable, FormatterError
}

export class FormatToolError extends Error {
    cause: FormatToolErrorCause;
    formatterMessage: string | undefined;

    constructor(cause: FormatToolErrorCause) {
        super();
        this.cause = cause;
    }
}

/**
 * Finds the Zircon build output directory given a Fuchsia repository root.
 *
 * This function derives the correct filesystem path, but it doesn't check to
 * ensure that the path exists. Callers are responsible for ensuring that the
 * resulting path exists and has the expected contents.
 *
 * @param fuchsiaRoot the filesystem path to the root of the Fuchsia
 * repository.
 * @returns the filesystem path to the root of the Zircon build output
 * directory.
 */
function deriveZirconOutPath(fuchsiaRoot: string): string | null {
    const buildOutputPointer = path.join(fuchsiaRoot, '.fx-build-dir');
    let outputRoot
    try {
        outputRoot = fs.readFileSync(buildOutputPointer, { encoding: 'utf8' }).trim();
    } catch (err) {
        // TODO: proper error handling
        return null;
    }
    return path.join(fuchsiaRoot, outputRoot + '.zircon');
}

/**
 * Finds the fidl-format tool given a Zircon output repository root.
 *
 * This function derives the correct filesystem path, but it doesn't check to
 * ensure that the path exists. Callers are responsible for ensuring that the
 * resulting path exists and has the expected contents.
 *
 * @param zirconRoot the filesystem path to the root of the Fuchsia
 * repository.
 * @returns the filesystem path to the fidl-format tool.
 */
function deriveFidlFormatPath(zirconRoot: string): string | null {
    return path.join(zirconRoot, 'tools', 'fidl-format');
}

/**
 * Attempts to find the fidl-format tool in the current directory, returning
 * the path to the tool if it's present and executable by the current user.
 *
 * @param folderPath The path to the folder to search in.
 * @returns The path to the fidl-format tool in folderPath or null if the tool can't be found or isn't executable.
 */
function findFidlFormatInFolder(folderPath: string): string | null {
    const zirconRoot = deriveZirconOutPath(folderPath);
    if (!zirconRoot) {
        return null;
    }

    const toolPath = deriveFidlFormatPath(zirconRoot);
    if (!toolPath) {
        return null;
    }

    try {
        fs.accessSync(toolPath, fs.constants.X_OK);
    } catch (err) {
        return null;
    }

    return toolPath;
}

/**
 * Attempts to find the fidl-format tool by asking VS Code to find the root of
 * the Fuchsia repository.
 *
 * @returns the absolute path to fidl-format or null if it couldn't be found.
 */
async function guessFidlFormatPathFromWorkspace(): Promise<string | null> {
    const uris = await vscode.workspace.findFiles('.fx-build-dir', null, 1);
    if (uris.length < 1) {
        return null;
    }

    for (const uri of uris) {
        if (uri.scheme !== 'file') {
            // If the repository isn't local, fidl-format won't be runnable
            // even if present.
            continue;
        }

        const basePath = path.dirname(uri.fsPath);
        const toolPath = findFidlFormatInFolder(basePath);
        if (toolPath == null) {
            continue;
        }

        return toolPath;
    }

    return null;
}

/**
 * Attempts to find the fidl-format tool by traversing the directory tree up
 * from the root of each workspace folder toward the root of the filesystem.
 *
 * @returns the absolute path to fidl-format or null if it couldn't be found.
 */
function guessFidlFormatPathFromAncestors(): string | null {
    const folders = vscode.workspace.workspaceFolders;
    if (!folders) {
        return null;
    }

    for (const folder of folders) {
        if (folder.uri.scheme !== 'file') {
            // If the repository isn't local, fidl-format won't be runnable
            // even if present.
            continue;
        }

        let folderPath;

        // Traverse through parent repositories until the direct child of the
        // root directory.
        for (folderPath = folder.uri.fsPath;
            path.dirname(folderPath) != folderPath;
            folderPath = path.dirname(folderPath)) {

            const toolPath = findFidlFormatInFolder(folderPath);
            if (toolPath) {
                return toolPath;
            }
        }

        // Also check the root directory.
        const toolPath = findFidlFormatInFolder(folderPath);
        if (toolPath) {
            return toolPath;
        }
    }

    return null;
}

/**
 * Gets the fidl-format tool path as configured in VS Code preferences.
 *
 * @returns the path to fidl-format as configured by the user, or `null` if the
 * tool isn't set.
 */
export function getFidlFormatToolPathFromPreferences(): string | null {
    let formatTool: string | undefined | null
        = vscode.workspace.getConfiguration('fidl').get('formatTool');

    try {
        fs.accessSync(toolPath, fs.constants.X_OK);
    } catch (err) {
        throw new FormatToolError(FormatToolErrorCause.ToolNotExecutable);
    }

    if (formatTool) {
        return formatTool;
    } else {
        return null;
    }
}

/**
 * Checks whether the path to fidl-format has been filled out. If the default
 * value of an empty string is found, an error is shown as a notification.
 */
export async function guessFidlFormatToolPath(): Promise<string> {
    let formatTool: string | undefined | null
        = getFidlFormatToolPathFromPreferences();

    // Guessing by ancestor is faster than searching a large workspace for the
    // Fuchsia root, so we try this approach first.
    if (!formatTool) {
        formatTool = guessFidlFormatPathFromAncestors();
    }

    if (!formatTool) {
        formatTool = await guessFidlFormatPathFromWorkspace();
    }

    if (!formatTool) {
        throw new FormatToolError(FormatToolErrorCause.ToolNotSpecified);
    }

    try {
        // Throws if tool is not present or not executable.
        fs.accessSync(formatTool, fs.constants.X_OK);
    } catch (err) {
        throw new FormatToolError(FormatToolErrorCause.ToolNotExecutable);
    }

    return formatTool;
}
