/* --------------------------------------------------------------------------------------------
* 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.DockerFormatter = void 0;
var vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
var vscode_languageserver_types_1 = require("vscode-languageserver-types");
var dockerfile_ast_1 = require("dockerfile-ast");
var DockerFormatter = /** @class */ (function () {
    function DockerFormatter() {
    }
    DockerFormatter.prototype.getIndentation = function (formattingOptions) {
        var indentation = "\t";
        if (formattingOptions && formattingOptions.insertSpaces) {
            indentation = "";
            for (var i = 0; i < formattingOptions.tabSize; i++) {
                indentation = indentation + " ";
            }
        }
        return indentation;
    };
    /**
     * Creates a TextEdit for formatting the given document.
     *
     * @param document the document being formatted
     * @param start the start offset of the document's content to be replaced
     * @param end the end offset of the document's content to be replaced
     * @param indent true if this block should be replaced with an indentation, false otherwise
     * @param indentation the string to use for an indentation
     */
    DockerFormatter.prototype.createFormattingEdit = function (document, start, end, indent, indentation) {
        if (indent) {
            return vscode_languageserver_types_1.TextEdit.replace({
                start: document.positionAt(start),
                end: document.positionAt(end)
            }, indentation);
        }
        else {
            return vscode_languageserver_types_1.TextEdit.del({
                start: document.positionAt(start),
                end: document.positionAt(end)
            });
        }
    };
    DockerFormatter.prototype.formatOnType = function (content, position, ch, options) {
        var dockerfile = dockerfile_ast_1.DockerfileParser.parse(content);
        // check that the inserted character is the escape character
        if (dockerfile.getEscapeCharacter() === ch) {
            for (var _i = 0, _a = dockerfile.getComments(); _i < _a.length; _i++) {
                var comment = _a[_i];
                // ignore if we're in a comment
                if (comment.getRange().start.line === position.line) {
                    return [];
                }
            }
            var directive = dockerfile.getDirective();
            // ignore if we're in the parser directive
            if (directive && position.line === 0) {
                return [];
            }
            var document = vscode_languageserver_textdocument_1.TextDocument.create("", "", 0, content);
            validityCheck: for (var i = document.offsetAt(position); i < content.length; i++) {
                switch (content.charAt(i)) {
                    case ' ':
                    case '\t':
                        break;
                    case '\r':
                    case '\n':
                        break validityCheck;
                    default:
                        // not escaping a newline, no need to format the next line
                        return [];
                }
            }
            var lines = [position.line + 1];
            var indentedLines = [];
            indentedLines[lines[0]] = true;
            return this.formatLines(document, document.getText(), lines, indentedLines, options);
        }
        return [];
    };
    DockerFormatter.prototype.formatRange = function (content, range, options) {
        var lines = [];
        for (var i = range.start.line; i <= range.end.line; i++) {
            lines.push(i);
        }
        return this.format(content, lines, options);
    };
    /**
     * Formats the specified lines of the given document based on the
     * provided formatting options.
     *
     * @param document the text document to format
     * @param lines the lines to format
     * @param options the formatting options to use to perform the format
     * @return the text edits to apply to format the lines of the document
     */
    DockerFormatter.prototype.format = function (content, lines, options) {
        var document = vscode_languageserver_textdocument_1.TextDocument.create("", "", 0, content);
        var dockerfile = dockerfile_ast_1.DockerfileParser.parse(content);
        var indentedLines = [];
        for (var i = 0; i < document.lineCount; i++) {
            indentedLines[i] = false;
        }
        for (var _i = 0, _a = dockerfile.getInstructions(); _i < _a.length; _i++) {
            var instruction = _a[_i];
            var range = instruction.getRange();
            indentedLines[range.start.line] = false;
            for (var i = range.start.line + 1; i <= range.end.line; i++) {
                indentedLines[i] = true;
            }
        }
        return this.formatLines(document, content, lines, indentedLines, options);
    };
    DockerFormatter.prototype.formatLines = function (document, content, lines, indentedLines, options) {
        var indentation = this.getIndentation(options);
        var edits = [];
        lineCheck: for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) {
            var line = lines_1[_i];
            var startOffset = document.offsetAt(vscode_languageserver_types_1.Position.create(line, 0));
            for (var i = startOffset; i < content.length; i++) {
                switch (content.charAt(i)) {
                    case ' ':
                    case '\t':
                        break;
                    case '\r':
                    case '\n':
                        if (i !== startOffset) {
                            // only whitespace on this line, trim it
                            var edit = vscode_languageserver_types_1.TextEdit.del({
                                start: document.positionAt(startOffset),
                                end: document.positionAt(i)
                            });
                            edits.push(edit);
                        }
                        // process the next line
                        continue lineCheck;
                    default:
                        // non-whitespace encountered
                        if (i !== startOffset || indentedLines[line]) {
                            var edit = this.createFormattingEdit(document, startOffset, i, indentedLines[line], indentation);
                            edits.push(edit);
                        }
                        // process the next line
                        continue lineCheck;
                }
            }
            if (startOffset < content.length) {
                // only whitespace on the last line, trim it
                var edit = vscode_languageserver_types_1.TextEdit.del({
                    start: document.positionAt(startOffset),
                    end: document.positionAt(content.length)
                });
                edits.push(edit);
            }
        }
        return edits;
    };
    return DockerFormatter;
}());
exports.DockerFormatter = DockerFormatter;
