/* --------------------------------------------------------------------------------------------
 * 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.DockerDefinition = void 0;
var vscode_languageserver_types_1 = require("vscode-languageserver-types");
var docker_1 = require("./docker");
var dockerfile_ast_1 = require("dockerfile-ast");
var DockerDefinition = /** @class */ (function () {
    function DockerDefinition() {
    }
    DockerDefinition.prototype.computeBuildStageDefinition = function (dockerfile, position) {
        var source = undefined;
        for (var _i = 0, _a = dockerfile.getCOPYs(); _i < _a.length; _i++) {
            var instruction = _a[_i];
            var flag = instruction.getFromFlag();
            if (flag) {
                var range = flag.getValueRange();
                if (range && range.start.line === position.line && range.start.character <= position.character && position.character <= range.end.character) {
                    source = flag.getValue();
                    break;
                }
            }
        }
        for (var _b = 0, _c = dockerfile.getFROMs(); _b < _c.length; _b++) {
            var instruction = _c[_b];
            var range = instruction.getBuildStageRange();
            if (range) {
                if (range.start.line === position.line && range.start.character <= position.character && position.character <= range.end.character) {
                    // cursor in FROM's build stage itself
                    return range;
                }
                else if (source !== undefined && instruction.getBuildStage().toLowerCase() === source.toLowerCase()) {
                    // FROM's build stage matches what's in COPY
                    return range;
                }
            }
            range = instruction.getImageNameRange();
            if (docker_1.Util.isInsideRange(position, range)) {
                var stageName = instruction.getImageName();
                for (var _d = 0, _e = dockerfile.getFROMs(); _d < _e.length; _d++) {
                    var from = _e[_d];
                    if (stageName === from.getBuildStage() && from.getRange().start.line < range.start.line) {
                        return from.getBuildStageRange();
                    }
                }
                return null;
            }
        }
        return null;
    };
    DockerDefinition.computeVariableDefinition = function (image, position) {
        var variableName = null;
        for (var _i = 0, _a = image.getARGs(); _i < _a.length; _i++) {
            var arg = _a[_i];
            var property = arg.getProperty();
            // might be an ARG with no arguments
            if (property) {
                // is the caret inside the definition itself
                if (docker_1.Util.isInsideRange(position, property.getNameRange())) {
                    variableName = property.getName();
                    break;
                }
            }
        }
        if (variableName === null) {
            variableCheck: for (var _b = 0, _c = image.getENVs(); _b < _c.length; _b++) {
                var env = _c[_b];
                var properties = env.getProperties();
                for (var _d = 0, properties_1 = properties; _d < properties_1.length; _d++) {
                    var property = properties_1[_d];
                    // is the caret inside the definition itself
                    if (docker_1.Util.isInsideRange(position, property.getNameRange())) {
                        variableName = property.getName();
                        break variableCheck;
                    }
                }
            }
        }
        if (variableName === null) {
            variableCheck: for (var _e = 0, _f = image.getInstructions(); _e < _f.length; _e++) {
                var instruction = _f[_e];
                for (var _g = 0, _h = instruction.getVariables(); _g < _h.length; _g++) {
                    var variable = _h[_g];
                    if (docker_1.Util.isInsideRange(position, variable.getNameRange())) {
                        variableName = variable.getName();
                        break variableCheck;
                    }
                }
            }
        }
        for (var _j = 0, _k = image.getInstructions(); _j < _k.length; _j++) {
            var instruction = _k[_j];
            if (instruction instanceof dockerfile_ast_1.Arg) {
                var property = instruction.getProperty();
                // might be an ARG with no arguments
                if (property && property.getName() === variableName) {
                    return property;
                }
            }
            else if (instruction instanceof dockerfile_ast_1.Env) {
                var properties = instruction.getProperties();
                for (var _l = 0, properties_2 = properties; _l < properties_2.length; _l++) {
                    var property = properties_2[_l];
                    if (property.getName() === variableName) {
                        return property;
                    }
                }
            }
        }
        return null;
    };
    DockerDefinition.findDefinition = function (dockerfile, position) {
        for (var _i = 0, _a = dockerfile.getFROMs(); _i < _a.length; _i++) {
            var from = _a[_i];
            for (var _b = 0, _c = from.getVariables(); _b < _c.length; _b++) {
                var variable = _c[_b];
                if (docker_1.Util.isInsideRange(position, variable.getNameRange())) {
                    for (var _d = 0, _e = dockerfile.getInitialARGs(); _d < _e.length; _d++) {
                        var arg = _e[_d];
                        var property = arg.getProperty();
                        if (property && property.getName() === variable.getName()) {
                            return property;
                        }
                    }
                    return null;
                }
            }
        }
        var image = dockerfile.getContainingImage(position);
        if (image === null) {
            return null;
        }
        return DockerDefinition.computeVariableDefinition(image, position);
    };
    DockerDefinition.checkHeredocs = function (heredocs, position) {
        for (var _i = 0, heredocs_1 = heredocs; _i < heredocs_1.length; _i++) {
            var heredoc = heredocs_1[_i];
            var nameRange = heredoc.getNameRange();
            if (docker_1.Util.isInsideRange(position, nameRange)) {
                return docker_1.Util.isEmpty(nameRange) ? null : nameRange;
            }
            var delimiterRange = heredoc.getDelimiterRange();
            if (delimiterRange !== null && docker_1.Util.isInsideRange(position, delimiterRange)) {
                return nameRange;
            }
        }
        return null;
    };
    DockerDefinition.computeHeredocDefinition = function (dockerfile, position) {
        for (var _i = 0, _a = dockerfile.getInstructions(); _i < _a.length; _i++) {
            var instruction = _a[_i];
            if (instruction instanceof dockerfile_ast_1.Copy) {
                var range = DockerDefinition.checkHeredocs(instruction.getHeredocs(), position);
                if (range !== null) {
                    return range;
                }
            }
            else if (instruction instanceof dockerfile_ast_1.Run) {
                var range = DockerDefinition.checkHeredocs(instruction.getHeredocs(), position);
                if (range !== null) {
                    return range;
                }
            }
        }
        return null;
    };
    DockerDefinition.prototype.computeVariableDefinition = function (dockerfile, position) {
        var property = DockerDefinition.findDefinition(dockerfile, position);
        return property ? property.getNameRange() : null;
    };
    DockerDefinition.prototype.computeDefinitionRange = function (content, position) {
        var dockerfile = dockerfile_ast_1.DockerfileParser.parse(content);
        var range = this.computeBuildStageDefinition(dockerfile, position);
        if (range === null) {
            range = this.computeVariableDefinition(dockerfile, position);
            if (range === null) {
                return DockerDefinition.computeHeredocDefinition(dockerfile, position);
            }
        }
        return range;
    };
    DockerDefinition.prototype.computeDefinition = function (textDocument, content, position) {
        var range = this.computeDefinitionRange(content, position);
        if (range !== null) {
            return vscode_languageserver_types_1.Location.create(textDocument.uri, range);
        }
        return null;
    };
    return DockerDefinition;
}());
exports.DockerDefinition = DockerDefinition;
