// This file implements the UI for the output panel (the right half of the UI)

import { BuildResponse, TransformResponse } from "./ipc";
import { generateSourceMapLink, toggleInlineSourceMapLink } from "./sourcemap";

export interface OutputFile {
  path: string;
  text: string;
}

export function prettyPrintErrorAsStderr(err: RichError): string {
  let text = `\x1B[31m✘ \x1B[41;31m[\x1B[41;97mERROR\x1B[41;31m]\x1B[0m \x1B[1m${
    (err && err.message) || err
  }\x1B[0m`;
  const location = err && err.location_;
  const notes = err && err.notes_;
  if (location) text += prettyPrintLocationAsStderr(location);
  if (notes) {
    for (const note of notes) {
      text += `\n  ${note.text_}`;
      if (note.location_) text += prettyPrintLocationAsStderr(note.location_);
    }
  }
  return text;
}

export type RichError = Error & {
  location_?: Location;
  notes_: { text_: string; location_?: Location }[];
};

export interface Location {
  file_: string;
  line_: number; // 1-based
  column_: number; // 0-based, in UTF-16 code units
  length_: number; // in UTF-16 code units
  lineText_: string;
  suggestion_?: string;
}

function prettyPrintLocationAsStderr({
  file_,
  line_,
  column_,
  length_,
  lineText_,
  suggestion_,
}: Location): string {
  let last = length_ < 2 ? "^" : "~".repeat(length_);
  let result = `\n\n    ${file_}:${line_}:${column_}:\n`;
  result +=
    `\x1B[37m${line_.toString().padStart(7)} │ ${lineText_.slice(0, column_)}` +
    `\x1B[32m${lineText_.slice(column_, column_ + length_)}` +
    `\x1B[37m${lineText_.slice(column_ + length_)}\n`;
  if (suggestion_) {
    result += `        │ ${" ".repeat(column_)}\x1B[32m${last}\x1B[37m\n`;
    last = suggestion_;
  }
  result += `        ╵ ${" ".repeat(column_)}\x1B[32m${last}\x1B[0m\n`;
  return result;
}

export function updateTransformOutput({
  code_,
  map_,
  mangleCache_,
  legalComments_,
  stderr_,
}: TransformResponse): void {}

export function updateBuildOutput(
  { outputFiles_, metafile_, mangleCache_, stderr_ }: BuildResponse,
  entryPointCount: number
): void {}

export function showLoadingMessage(version: string | null): void {}

export function showLoadingFailure(error: string): void {}

export function terminalEscapeCodesToHTML(text: string): string {
  return (
    "<span>" +
    text
      .replace(/&/g, "&amp;")
      .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;")
      .replace(/\033\[([^m]*)m/g, (_, escape) => {
        switch (escape) {
          case "1":
            return '</span><span class="color-bold">';
          case "31":
            return '</span><span class="color-red">';
          case "32":
            return '</span><span class="color-green">';
          case "33":
            return '</span><span class="color-yellow">';
          case "35":
            return '</span><span class="color-magenta">'; // This is generated by warnings in version 0.14.0 and earlier
          case "37":
            return '</span><span class="color-dim">';
          case "41;31":
            return '</span><span class="bg-red color-red">';
          case "41;97":
            return '</span><span class="bg-red color-white">';
          case "43;33":
            return '</span><span class="bg-yellow color-yellow">';
          case "43;30":
            return '</span><span class="bg-yellow color-black">';
          case "0":
            return "</span><span>";
        }
        throw new Error(`Unknown escape sequence: ${escape}`);
      }) +
    "</span>"
  );
}
