import {Position, TextDocument} from "vscode-languageserver-textdocument";
import {Range} from "vscode-languageserver-types";

const PLACEHOLDER_KEY = "key";

// Transform a document to work around YAML parsing issues
// Based on `_transform` in https://github.com/cschleiden/github-actions-parser/blob/main/src/lib/parser/complete.ts#L311
export function transform(doc: TextDocument, pos: Position): [TextDocument, Position] {
  let offset = doc.offsetAt(pos);

  const lineRange: Range = {
    start: {line: pos.line, character: 0},
    end: {line: pos.line, character: Number.MAX_SAFE_INTEGER}
  };

  let line = doc.getText(lineRange);

  // If the line includes a new-line char, strip that out
  const newLinePos = line.indexOf("\n");
  if (newLinePos >= 0) {
    line = line.substring(0, newLinePos);
  }
  lineRange.end.character = line.length;

  const linePos = pos.character;

  // Special case for Actions, if this line contains an expression marker, do _not_ transform. This is
  // an ugly fix for auto-completion in multi-line YAML strings. At this point in the process, we cannot
  // determine if a line is in such a multi-line string.
  if (line.indexOf("${{") !== -1) {
    return [doc, pos];
  }

  const containsColon = line.indexOf(":") !== -1;
  if (!containsColon) {
    const trimmedLine = line.trim();
    if (trimmedLine === "" || trimmedLine === "-") {
      // Pos in sequence or empty line
      let spacer = "";
      if (trimmedLine === "-" && !line.endsWith(" ")) {
        spacer = " ";
        offset++;
      }

      line =
        line.substring(0, linePos) +
        spacer +
        PLACEHOLDER_KEY +
        (trimmedLine === "-" ? "" : ":") +
        line.substring(linePos);

      // Adjust pos by one to prevent a sequence node being marked as active
      offset++;
    } else if (!trimmedLine.startsWith("-")) {
      // Add `:` to end of line
      line = line + ":";
    }
  }

  const newDoc = TextDocument.create(doc.uri, doc.languageId, doc.version, doc.getText());

  TextDocument.update(
    newDoc,
    [
      {
        range: lineRange,
        text: line
      }
    ],
    newDoc.version + 1
  );

  return [newDoc, newDoc.positionAt(offset)];
}
