/* --------------------------------------------------------------------------------------------
 * Copyright (c) Remy Suen. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for license information.
 * ------------------------------------------------------------------------------------------ */
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.DockerHover = void 0;
var vscode_languageserver_types_1 = require("vscode-languageserver-types");
var dockerfile_ast_1 = require("dockerfile-ast");
var docker_1 = require("./docker");
var DockerHover = /** @class */ (function () {
    function DockerHover(markdown, plainText) {
        this.markdown = markdown;
        this.plainText = plainText;
    }
    DockerHover.prototype.onHover = function (content, position, markupKind) {
        var dockerfile = dockerfile_ast_1.DockerfileParser.parse(content);
        var image = dockerfile.getContainingImage(position);
        if (!image) {
            // position is invalid, not inside the Dockerfile
            return null;
        }
        var key = this.computeHoverKey(dockerfile, position);
        if (key) {
            // if it's not a raw value, apply markup if necessary
            if (markupKind && markupKind.length > 0) {
                switch (markupKind[0]) {
                    case vscode_languageserver_types_1.MarkupKind.Markdown:
                        var markdownDocumentation = this.markdown.getMarkdown(key);
                        if (markdownDocumentation) {
                            return {
                                contents: {
                                    kind: vscode_languageserver_types_1.MarkupKind.Markdown,
                                    value: markdownDocumentation.contents
                                }
                            };
                        }
                        return null;
                    case vscode_languageserver_types_1.MarkupKind.PlainText:
                        var plainTextDocumentation = this.plainText.getDocumentation(key);
                        if (plainTextDocumentation) {
                            return {
                                contents: {
                                    kind: vscode_languageserver_types_1.MarkupKind.PlainText,
                                    value: plainTextDocumentation
                                }
                            };
                        }
                }
                return null;
            }
            var hover = this.markdown.getMarkdown(key);
            return hover === undefined ? null : hover;
        }
        for (var _i = 0, _a = image.getInstructions(); _i < _a.length; _i++) {
            var instruction = _a[_i];
            if (instruction instanceof dockerfile_ast_1.Arg) {
                // hovering over an argument defined by ARG
                var property = instruction.getProperty();
                if (property && docker_1.Util.isInsideRange(position, property.getNameRange()) && property.getValue() !== null) {
                    return { contents: property.getValue() };
                }
            }
            if (instruction instanceof dockerfile_ast_1.Env) {
                // hovering over an argument defined by ENV
                for (var _b = 0, _c = instruction.getProperties(); _b < _c.length; _b++) {
                    var property = _c[_b];
                    if (docker_1.Util.isInsideRange(position, property.getNameRange()) && property.getValue() !== null) {
                        return {
                            contents: property.getValue()
                        };
                    }
                }
            }
        }
        for (var _d = 0, _e = image.getInstructions(); _d < _e.length; _d++) {
            var instruction = _e[_d];
            for (var _f = 0, _g = instruction.getVariables(); _f < _g.length; _f++) {
                var variable = _g[_f];
                // are we hovering over a variable
                if (docker_1.Util.isInsideRange(position, variable.getNameRange())) {
                    var resolved = dockerfile.resolveVariable(variable.getName(), variable.getNameRange().start.line);
                    if (resolved || resolved === "") {
                        return { contents: resolved };
                    }
                    else if (resolved === null) {
                        return null;
                    }
                }
            }
        }
        return null;
    };
    /**
     * Analyzes the Dockerfile at the given position to determine if the user
     * is hovering over a keyword, a flag, or a directive.
     *
     * @param dockerfile the Dockerfile to check
     * @param position the place that the user is hovering over
     * @return the string key value for the keyword, flag, or directive that's
     *         being hovered over, or null if the user isn't hovering over
     *         such a word
     */
    DockerHover.prototype.computeHoverKey = function (dockerfile, position) {
        for (var _i = 0, _a = dockerfile.getDirectives(); _i < _a.length; _i++) {
            var directive = _a[_i];
            var range = directive.getNameRange();
            switch (directive.getDirective()) {
                case dockerfile_ast_1.Directive.escape:
                    if (docker_1.Util.isInsideRange(position, range)) {
                        return dockerfile_ast_1.Directive.escape;
                    }
                    break;
                case dockerfile_ast_1.Directive.syntax:
                    if (docker_1.Util.isInsideRange(position, range)) {
                        return dockerfile_ast_1.Directive.syntax;
                    }
                    break;
            }
        }
        var image = dockerfile.getContainingImage(position);
        for (var _b = 0, _c = image.getInstructions(); _b < _c.length; _b++) {
            var instruction = _c[_b];
            var instructionRange = instruction.getInstructionRange();
            if (docker_1.Util.isInsideRange(position, instructionRange)) {
                return instruction.getKeyword();
            }
            if (instruction instanceof dockerfile_ast_1.Onbuild) {
                // hovering over a trigger instruction of an ONBUILD
                var range = instruction.getTriggerRange();
                if (docker_1.Util.isInsideRange(position, range)) {
                    return instruction.getTrigger();
                }
            }
            var hover = this.getFlagsHover(position, instruction);
            if (hover !== null) {
                return hover;
            }
        }
        return null;
    };
    DockerHover.prototype.getFlagsHover = function (position, instruction) {
        switch (instruction.getKeyword()) {
            case "ADD":
                var addFlags = instruction.getFlags();
                for (var _i = 0, addFlags_1 = addFlags; _i < addFlags_1.length; _i++) {
                    var flag = addFlags_1[_i];
                    if (docker_1.Util.isInsideRange(position, flag.getNameRange())) {
                        switch (flag.getName()) {
                            case "chown":
                                return "ADD_FlagChown";
                        }
                    }
                }
                break;
            case "COPY":
                var copyFlags = instruction.getFlags();
                for (var _a = 0, copyFlags_1 = copyFlags; _a < copyFlags_1.length; _a++) {
                    var flag = copyFlags_1[_a];
                    if (docker_1.Util.isInsideRange(position, flag.getNameRange())) {
                        switch (flag.getName()) {
                            case "chown":
                                return "COPY_FlagChown";
                            case "from":
                                return "COPY_FlagFrom";
                        }
                    }
                }
                break;
            case "FROM":
                var fromFlags = instruction.getFlags();
                for (var _b = 0, fromFlags_1 = fromFlags; _b < fromFlags_1.length; _b++) {
                    var flag = fromFlags_1[_b];
                    if (docker_1.Util.isInsideRange(position, flag.getNameRange())) {
                        if (flag.getName() === "platform") {
                            return "FROM_FlagPlatform";
                        }
                        return null;
                    }
                }
                break;
            case "HEALTHCHECK":
                var flags = instruction.getFlags();
                for (var _c = 0, flags_1 = flags; _c < flags_1.length; _c++) {
                    var flag = flags_1[_c];
                    if (docker_1.Util.isInsideRange(position, flag.getNameRange())) {
                        switch (flag.getName()) {
                            case "interval":
                                return "HEALTHCHECK_FlagInterval";
                            case "retries":
                                return "HEALTHCHECK_FlagRetries";
                            case "start-interval":
                                return "HEALTHCHECK_FlagStartInterval";
                            case "start-period":
                                return "HEALTHCHECK_FlagStartPeriod";
                            case "timeout":
                                return "HEALTHCHECK_FlagTimeout";
                        }
                        return null;
                    }
                }
                break;
            case "ONBUILD":
                var trigger = instruction.getTriggerInstruction();
                if (trigger !== null) {
                    return this.getFlagsHover(position, trigger);
                }
                break;
        }
        return null;
    };
    return DockerHover;
}());
exports.DockerHover = DockerHover;
