"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getYamlValidation = exports.doValidate = void 0;
const interval_tree_1 = __importDefault(require("@flatten-js/interval-tree"));
const vscode_languageserver_1 = require("vscode-languageserver");
const yaml_1 = require("../utils/yaml");
const commandRunner_1 = require("../utils/commandRunner");
/**
 * Validates the given document.
 * @param textDocument - the document to validate
 * @param linter - uses linter
 * @param quick - only re-evaluates YAML validation and uses lint cache
 * @returns Map of diagnostics per file.
 */
function doValidate(textDocument, validationManager, quick = true, context, connection) {
    return __awaiter(this, void 0, void 0, function* () {
        let diagnosticsByFile;
        if (quick || !context) {
            // get validation from cache
            diagnosticsByFile =
                validationManager.getValidationFromCache(textDocument.uri) ||
                    new Map();
        }
        else {
            // full validation with ansible-lint or ansible syntax-check (if ansible-lint is not installed or disabled)
            const settings = yield context.documentSettings.get(textDocument.uri);
            if (!settings.validation.enabled) {
                console.log("Validation disabled");
                // this is done to remove the cache as well
                const blankDiagnostics = new Map();
                blankDiagnostics.set(textDocument.uri, []);
                validationManager.processDiagnostics(textDocument.uri, blankDiagnostics);
                validationManager.cacheDiagnostics(textDocument.uri, blankDiagnostics);
                return blankDiagnostics;
            }
            // validation using ansible-lint
            if (settings.validation.lint.enabled) {
                const commandRunner = new commandRunner_1.CommandRunner(connection, context, settings);
                const lintExecutable = settings.executionEnvironment.enabled
                    ? "ansible-lint"
                    : settings.validation.lint.path;
                const lintAvailability = yield commandRunner.getExecutablePath(lintExecutable);
                console.debug("Path for lint: ", lintAvailability);
                if (lintAvailability) {
                    console.debug("Validating using ansible-lint");
                    diagnosticsByFile = yield context.ansibleLint.doValidate(textDocument);
                }
                else {
                    connection === null || connection === void 0 ? void 0 : connection.window.showErrorMessage("Ansible-lint is not available. Kindly check the path or disable validation using ansible-lint");
                }
            }
            // validate using ansible-playbook --syntax-check
            else {
                console.debug("Validating using ansible syntax-check");
                if ((0, yaml_1.isPlaybook)(textDocument)) {
                    console.debug("playbook file");
                    diagnosticsByFile = yield context.ansiblePlaybook.doValidate(textDocument);
                }
                else {
                    console.debug("non-playbook file");
                    diagnosticsByFile = new Map();
                }
            }
            if (!diagnosticsByFile.has(textDocument.uri)) {
                // In case there are no diagnostics for the file that triggered the
                // validation, set an empty array in order to clear the validation.
                diagnosticsByFile.set(textDocument.uri, []);
            }
            validationManager.cacheDiagnostics(textDocument.uri, diagnosticsByFile);
        }
        // attach quick validation for the inspected file
        for (const [fileUri, fileDiagnostics] of diagnosticsByFile) {
            if (textDocument.uri === fileUri) {
                fileDiagnostics.push(...getYamlValidation(textDocument));
            }
        }
        validationManager.processDiagnostics(textDocument.uri, diagnosticsByFile);
        return diagnosticsByFile;
    });
}
exports.doValidate = doValidate;
function getYamlValidation(textDocument) {
    const diagnostics = [];
    const yDocuments = (0, yaml_1.parseAllDocuments)(textDocument.getText());
    const rangeTree = new interval_tree_1.default();
    yDocuments.forEach((yDoc) => {
        yDoc.errors.forEach((error) => {
            const [errStart, errEnd] = error.pos;
            if (errStart) {
                const start = textDocument.positionAt(errStart !== undefined ? errStart : null);
                const end = textDocument.positionAt(errEnd !== undefined ? errEnd : null);
                const range = vscode_languageserver_1.Range.create(start, end);
                let severity;
                switch (error.name) {
                    case "YAMLParseError":
                        severity = vscode_languageserver_1.DiagnosticSeverity.Error;
                        break;
                    case "YAMLWarning":
                        severity = vscode_languageserver_1.DiagnosticSeverity.Warning;
                        break;
                    default:
                        severity = vscode_languageserver_1.DiagnosticSeverity.Information;
                        break;
                }
                rangeTree.insert([error.linePos[0].line, error.linePos[1].line], {
                    message: error.message,
                    range: range || vscode_languageserver_1.Range.create(0, 0, 0, 0),
                    severity: severity,
                    source: "Ansible [YAML]",
                });
            }
        });
    });
    rangeTree.forEach((range, diag) => {
        diagnostics.push(diag);
    });
    return diagnostics;
}
exports.getYamlValidation = getYamlValidation;
//# sourceMappingURL=validationProvider.js.map