// deno-lint-disable-must-await-calls
import { Cursor } from "./cursor.ts";
import { colorize } from "./style.ts";
import { TerminalBlock, TerminalLayout } from "./TerminalLayout.ts";

export async function cliPrompt(
  message: string,
  block?: TerminalBlock,
): Promise<string> {
  const encoder = new TextEncoder();
  const input: string[] = [];

  await Deno.stdin.setRaw(true);

  const cursorVisible = Cursor["visible"];
  Cursor.show();

  let range: [number, number] = [0, 1];
  if (block) {
    range = block.setLines([message + " "]);
  } else {
    Deno.stdout.writeSync(encoder.encode(message + " "));
  }

  const buf = new Uint8Array(1);
  while (true) {
    const n = await Deno.stdin.read(buf);
    if (n === null) break;
    const byte = buf[0];

    if (byte === 3) { // Ctrl+C
      Deno.stdin.setRaw(false);
      block?.["layout"]?.clearAll();
      block?.clear();
      Deno.exit(130);
    }

    if (byte === 13) { // Enter
      break;
    } else if (byte === 127 || byte === 8) { // Backspace
      input.pop();
    } else if (byte >= 32 && byte <= 126) { // Printable chars
      input.push(String.fromCharCode(byte));
    }

    const line = message + " " + input.join("");
    if (block) {
      range = block.setLines([line], range);
    } else {
      Deno.stdout.writeSync(encoder.encode("\r\x1b[K" + line));
    }
  }

  await Deno.stdin.setRaw(false);
  if (!cursorVisible) {
    Cursor.hide();
  }
  Deno.stdout.writeSync(encoder.encode("\n"));

  return input.join("");
}

export function cliConfirm(message: string, block?: TerminalBlock) {
  return cliPrompt(message + " (y/n)", block).then((v) =>
    v.toLowerCase() === "y"
  );
}

export function cliAlert(message: string, block?: TerminalBlock) {
  return cliPrompt(
    message + colorize(" Press Enter to continue", "gray"),
    block,
  ).then((v) => {
    return v;
  });
}

export function cliLog(
  message: string | object | Array<unknown>,
  block?: TerminalBlock,
) {
  if (!block) {
    console.log(message);
  } else {
    if (typeof message === "object") message = Deno.inspect(message);
    block.setLines(message.split("\n"));
  }
}

if (import.meta.main) {
  Cursor.hide();
  const layout = new TerminalLayout();
  const title = new TerminalBlock();
  const block = new TerminalBlock();
  block.setPreserveHistory(true);
  // ScrollManager.enable(block);
  title.setLines(["Hello, World!"]);
  title.setFixedHeight(1);

  layout.register("title", title);
  layout.register("block", block);

  Deno.addSignalListener("SIGINT", () => {
    layout.clearAll();
    // console.clear();
    Deno.exit(0);
  });
  const name = await cliPrompt("Enter your name:", block);
  cliLog(`Hello, ${name}!`, block);
  const single = await cliConfirm("Are you single?", block);
  cliLog(single ? "Do you want to go out with me?" : "Okay", block);
  // ScrollManager.enable(block);
  const loopingConvo = [
    "No response?",
    "I guess that's okay",
    "Maybe I'll see you next week?",
    "Wow, really not going to say anything to me?",
    "Well, if that's how you feel",
  ];
  let convo = 0;
  setInterval(() => {
    cliLog(loopingConvo[convo % loopingConvo.length], block);
    convo++;
  }, 2000);
  // setTimeout(async () => {
  //   await cliAlert("Well, if that's that...", block);
  //   Deno.exit(0);
  // }, 10000);
}
