// Generated by ReScript, PLEASE EDIT WITH CARE
'use strict';

var Curry = require("rescript/lib/js/curry.js");
var Vscode = require("vscode");
var $$Promise = require("reason-promise/lib/js/src/js/promise.bs.js");
var Belt_Array = require("rescript/lib/js/belt_Array.js");
var Pervasives = require("rescript/lib/js/pervasives.js");
var Caml_option = require("rescript/lib/js/caml_option.js");
var Config$AgdaModeVscode = require("./Config.bs.js");
var Editor$AgdaModeVscode = require("./Editor.bs.js");
var Tokens$AgdaModeVscode = require("./Tokens.bs.js");
var Highlighting__SemanticToken$AgdaModeVscode = require("./Highlighting/Highlighting__SemanticToken.bs.js");

function decorateHole(editor, interval, index) {
  var $$document = editor.document;
  var backgroundRange = Editor$AgdaModeVscode.$$Range.fromInterval($$document, interval);
  var background = Editor$AgdaModeVscode.Decoration.highlightBackground(editor, "editor.selectionHighlightBackground", [backgroundRange]);
  var indexText = String(index);
  var innerInterval_0 = interval[0];
  var innerInterval_1 = interval[1] - 2 | 0;
  var innerInterval = [
    innerInterval_0,
    innerInterval_1
  ];
  var indexRange = Editor$AgdaModeVscode.$$Range.fromInterval($$document, innerInterval);
  var index$1 = Editor$AgdaModeVscode.Decoration.overlayText(editor, "editorLightBulb.foreground", indexText, indexRange);
  return [
          background,
          index$1
        ];
}

function make(param) {
  return {
          decorations: [],
          semanticTokens: []
        };
}

function clear(self) {
  Belt_Array.forEach(self.decorations, (function (param) {
          return Editor$AgdaModeVscode.Decoration.destroy(param[0]);
        }));
  self.decorations = [];
  
}

var destroy = clear;

function redecorate(self, editor) {
  return Belt_Array.forEach(self.decorations, (function (param) {
                return Editor$AgdaModeVscode.Decoration.decorate(editor, param[0], param[1]);
              }));
}

function classify(change, token) {
  var removedRange = change.range;
  var regex = /\r\n|\r|\n/;
  var lines = change.text.split(regex);
  var lineDetalOfRemovedRange = removedRange.end.line - removedRange.start.line | 0;
  var lineDelta = (lines.length - 1 | 0) - lineDetalOfRemovedRange | 0;
  var match;
  if (lineDelta > 0) {
    match = [
      lineDelta,
      -removedRange.end.character | 0
    ];
  } else if (lineDelta < 0) {
    var columnDelta = removedRange.end.character - removedRange.start.character | 0;
    match = [
      lineDelta,
      -columnDelta | 0
    ];
  } else {
    var columnDeltaOfRemovedRange = removedRange.end.character - removedRange.start.character | 0;
    var match$1 = Belt_Array.get(lines, lineDelta);
    var columnDelta$1;
    if (match$1 !== undefined) {
      var line = Caml_option.valFromOption(match$1);
      columnDelta$1 = line !== undefined ? line.length - columnDeltaOfRemovedRange | 0 : 0;
    } else {
      columnDelta$1 = 0;
    }
    match = [
      0,
      columnDelta$1
    ];
  }
  var lineDelta$1 = match[0];
  var tokenRange = Curry._1(Highlighting__SemanticToken$AgdaModeVscode.Module.SingleLineRange.toVsCodeRange, token.range);
  if (tokenRange.end.isBeforeOrEqual(removedRange.start)) {
    return /* NoOp */0;
  } else if (removedRange.contains(tokenRange) || tokenRange.start.isBefore(removedRange.start) && tokenRange.end.isAfter(removedRange.end)) {
    return /* Remove */1;
  } else if (token.range.line === removedRange.end.line) {
    return {
            TAG: 0,
            _0: lineDelta$1,
            _1: match[1],
            [Symbol.for("name")]: "Move"
          };
  } else if (lineDelta$1 === 0) {
    return /* NoOp */0;
  } else {
    return {
            TAG: 1,
            _0: lineDelta$1,
            [Symbol.for("name")]: "MoveLinesOnly"
          };
  }
}

function updateSemanticHighlighting(self, $$event) {
  var changes = $$event.contentChanges;
  var applyChange = function (tokens, change) {
    return Belt_Array.concatMany(Belt_Array.map(tokens, (function (token) {
                      var action = classify(change, token);
                      if (typeof action === "number") {
                        if (action === /* NoOp */0) {
                          return [token];
                        } else {
                          return [];
                        }
                      }
                      if (action.TAG !== /* Move */0) {
                        return [{
                                  range: {
                                    line: token.range.line + action._0 | 0,
                                    column: token.range.column
                                  },
                                  type_: token.type_,
                                  modifiers: token.modifiers
                                }];
                      }
                      var columnDelta = action._1;
                      return [{
                                range: {
                                  line: token.range.line + action._0 | 0,
                                  column: [
                                    Pervasives.abs(token.range.column[0] + columnDelta | 0),
                                    Pervasives.abs(token.range.column[1] + columnDelta | 0)
                                  ]
                                },
                                type_: token.type_,
                                modifiers: token.modifiers
                              }];
                    })));
  };
  return Belt_Array.forEach(changes, (function (change) {
                self.semanticTokens = applyChange(self.semanticTokens, change);
                
              }));
}

function getSemanticTokens(self) {
  return self.semanticTokens;
}

function apply(self, tokens, editor) {
  return $$Promise.flatMap(Tokens$AgdaModeVscode.readTempFiles(tokens, editor), (function (param) {
                if (Config$AgdaModeVscode.Highlighting.getHighlightWithThemeColors(undefined)) {
                  var match = Tokens$AgdaModeVscode.toDecorationsAndSemanticTokens(tokens, editor);
                  self.semanticTokens = match[1];
                  self.decorations = Belt_Array.concat(self.decorations, match[0]);
                  var $$document = editor.document;
                  var lineCount = $$document.lineCount;
                  var lastLine = $$document.lineAt(lineCount - 1 | 0);
                  var insertPosition = lastLine.range.end;
                  var deleteRange = new Vscode.Range(insertPosition, insertPosition.translate(0, 1));
                  return $$Promise.map($$Promise.flatMap($$Promise.flatMap(Editor$AgdaModeVscode.$$Text.batchInsert$p(editor, [insertPosition], " "), (function (succeed) {
                                        if (succeed) {
                                          return Editor$AgdaModeVscode.$$Text.batchReplace$p(editor, [[
                                                        deleteRange,
                                                        ""
                                                      ]]);
                                        } else {
                                          return $$Promise.resolved(false);
                                        }
                                      })), (function (param) {
                                    return $$document.save();
                                  })), (function (param) {
                                
                              }));
                }
                var decorations = Tokens$AgdaModeVscode.toDecorations(tokens, editor);
                self.decorations = Belt_Array.concat(self.decorations, decorations);
                return $$Promise.resolved(undefined);
              }));
}

var Module = {
  make: make,
  destroy: destroy,
  decorateHole: decorateHole,
  apply: apply,
  clear: clear,
  redecorate: redecorate,
  updateSemanticHighlighting: updateSemanticHighlighting,
  getSemanticTokens: getSemanticTokens
};

var Decoration;

var SemanticToken;

exports.Decoration = Decoration;
exports.SemanticToken = SemanticToken;
exports.Module = Module;
exports.make = make;
exports.destroy = destroy;
exports.decorateHole = decorateHole;
exports.apply = apply;
exports.clear = clear;
exports.redecorate = redecorate;
exports.updateSemanticHighlighting = updateSemanticHighlighting;
exports.getSemanticTokens = getSemanticTokens;
/* vscode Not a pure module */
