import command from "../config.json" assert { type: "json" };
import { HELP } from "./commands/help";
import { BANNER } from "./commands/banner";
import { ABOUT } from "./commands/about";
import { DEFAULT } from "./commands/default";
import { createWhoami } from "./commands/whoami";
import config from "../config.json";

let mutWriteLines = document.getElementById("write-lines");
let historyIdx = 0;
let tempInput = "";
let userInput: string;
let isRoot = false;
let isPasswordInput = false;
let passwordCounter = 0;
let bareMode = false;

const WRITELINESCOPY = mutWriteLines;
const TERMINAL = document.getElementById("terminal");
const USERINPUT = document.getElementById("user-input") as HTMLInputElement;
const INPUT_HIDDEN = document.getElementById("input-hidden");
const PASSWORD = document.getElementById("password-input");
const PASSWORD_INPUT = document.getElementById(
  "password-field"
) as HTMLInputElement;
const PRE_HOST = document.getElementById("pre-host");
const PRE_USER = document.getElementById("pre-user");
const HOST = document.getElementById("host");
const USER = document.getElementById("user");
const PROMPT = document.getElementById("prompt");
const COMMANDS = [
  "help",
  "about",
  "whoami",
  "banner",
  "clear",
  "key",
  "linkedin",
  "youtube",
  "nagini",
  "email",
];
const HISTORY: string[] = [];
const ROOT_PASSWORD = command.password;

const scrollToBottom = () => {
  const MAIN = document.getElementById("main");
  if (!MAIN) return;

  MAIN.scrollTop = MAIN.scrollHeight;
};

function userInputHandler(e: KeyboardEvent) {
  const key = e.key;

  switch (key) {
    case "Enter":
      e.preventDefault();
      if (!isPasswordInput) {
        enterKey();
      } else {
        passwordHandler();
      }

      scrollToBottom();
      break;
    case "Escape":
      USERINPUT.value = "";
      break;
    case "ArrowUp":
      arrowKeys(key);
      e.preventDefault();
      break;
    case "ArrowDown":
      arrowKeys(key);
      break;
    case "Tab":
      tabKey();
      e.preventDefault();
      break;
  }
}

function enterKey() {
  if (!mutWriteLines || !PROMPT) return;
  const resetInput = "";
  let newUserInput;
  userInput = USERINPUT.value;

  if (bareMode) {
    newUserInput = userInput;
  } else {
    newUserInput = `<span class='output'>${userInput}</span>`;
  }

  HISTORY.push(userInput);
  historyIdx = HISTORY.length;

  if (userInput === "clear") {
    commandHandler(userInput.toLowerCase().trim());
    USERINPUT.value = resetInput;
    userInput = resetInput;
    return;
  }

  const div = document.createElement("div");
  div.innerHTML = `<span id="prompt">${PROMPT.innerHTML}</span> ${newUserInput}`;

  if (mutWriteLines.parentNode) {
    mutWriteLines.parentNode.insertBefore(div, mutWriteLines);
  }

  if (userInput.trim().length !== 0) {
    commandHandler(userInput.toLowerCase().trim());
  }

  USERINPUT.value = resetInput;
  userInput = resetInput;
}

function tabKey() {
  let currInput = USERINPUT.value;

  for (const ele of COMMANDS) {
    if (ele.startsWith(currInput)) {
      USERINPUT.value = ele;
      return;
    }
  }
}

function arrowKeys(e: string) {
  switch (e) {
    case "ArrowDown":
      if (historyIdx !== HISTORY.length) {
        historyIdx += 1;
        USERINPUT.value = HISTORY[historyIdx];
        if (historyIdx === HISTORY.length) USERINPUT.value = tempInput;
      }
      break;
    case "ArrowUp":
      if (historyIdx === HISTORY.length) tempInput = USERINPUT.value;
      if (historyIdx !== 0) {
        historyIdx -= 1;
        USERINPUT.value = HISTORY[historyIdx];
      }
      break;
  }
}

function commandHandler(input: string) {
  if (input.startsWith("rm -rf") && input.trim() !== "rm -rf") {
    if (isRoot) {
      if (input === "rm -rf /" && !bareMode) {
        bareMode = true;

        setTimeout(() => {
          if (!TERMINAL || !WRITELINESCOPY) return;
          TERMINAL.innerHTML = "";
          TERMINAL.appendChild(WRITELINESCOPY);
          mutWriteLines = WRITELINESCOPY;
        });

        easterEggStyles();
        setTimeout(() => {
          writeLines(["What made you think that was a good idea?", "<br>"]);
        }, 200);

        setTimeout(() => {
          writeLines(["Now everything is ruined.", "<br>"]);
        }, 1200);
      } else if (input === "rm -rf /" && bareMode) {
        writeLines(["there's no more / folder.", "<br>"]);
      } else {
        if (bareMode) {
          writeLines(["What else are you trying to delete?", "<br>"]);
        } else {
          writeLines([
            "<br>",
            "Directory not found.",
            "type <span class='command'>'ls'</span> for a list of directories.",
            "<br>",
          ]);
        }
      }
    } else {
      writeLines(["Permission not granted.", "<br>"]);
    }
    return;
  }

  switch (input) {
    case "clear":
      setTimeout(() => {
        if (!TERMINAL || !WRITELINESCOPY) return;
        TERMINAL.innerHTML = "";
        TERMINAL.appendChild(WRITELINESCOPY);
        mutWriteLines = WRITELINESCOPY;
      });
      break;

    case "pwd":
      writeLines(["/home/guest", "<br>"]);
      break;

    case "banner":
      writeLines(bareMode ? ["Joshua SystemV", "<br>"] : BANNER);
      break;

    case "help":
      writeLines(
        bareMode
          ? ["maybe restarting your browser will fix this.", "<br>"]
          : HELP
      );
      break;

    case "whoami":
      writeLines(bareMode ? [`${command.username}`, "<br>"] : createWhoami());
      break;

    case "about":
      writeLines(bareMode ? ["Nothing to see here.", "<br>"] : ABOUT);
      break;

    case "key":
      writeLines([`Downloading to key/${config.social["pgp-key"]}...`, "<br>"]);
      setTimeout(() => {
        window.open(
          `https://src.panahifar.ir/pgp/C86437BFC43196C6.asc`,
          "_blank"
        );
      }, 500);
      break;

    case "linkedin":
      const linkedinUrl = `https://linkedin.com/in/${config.social.linkedin}`;
      writeLines([
        `Redirecting to Linkedin/${config.social.linkedin}...`,
        "<br>",
      ]);
      setTimeout(() => {
        window.open(linkedinUrl, "_blank");
      }, 500);
      break;

    case "youtube":
      const youtubeUrl = `https://www.youtube.com/@${config.social.youtube}`;
      writeLines([
        `Redirecting to Linkedin/${config.social.linkedin}...`,
        "<br>",
      ]);
      setTimeout(() => {
        window.open(youtubeUrl, "_blank");
      }, 500);
      break;

    case "nagini":
      writeLines([`Redirecting to negini/${config.social.git}...`, "<br>"]);
      setTimeout(() => {
        window.open(
          `https://src.panahifar.ir/${config.social.git}`,
          "_blank"
        );
      }, 500);
      break;

    case "email":
      writeLines([`Redirecting to ${config.social.email}...`, "<br>"]);
      setTimeout(() => {
        window.open(`mailto:${config.social.email}`, "_blank");
      }, 500);
      break;

    case "rm -rf":
      if (bareMode) {
        writeLines(["don't try again.", "<br>"]);
        break;
      }
      if (isRoot) {
        writeLines([
          "Usage: <span class='command'>'rm -rf &lt;dir&gt;'</span>",
          "<br>",
        ]);
      } else {
        writeLines(["Permission not granted.", "<br>"]);
      }
      break;
    case "su":
      if (bareMode) {
        writeLines(["no.", "<br>"]);
        break;
      }
      if (!PASSWORD) return;
      isPasswordInput = true;
      USERINPUT.disabled = true;

      if (INPUT_HIDDEN) INPUT_HIDDEN.style.display = "none";
      PASSWORD.style.display = "block";
      setTimeout(() => {
        PASSWORD_INPUT.focus();
      }, 100);

      break;
    case "ls":
      if (bareMode) {
        writeLines(["there's nothing to see here.", "<br>"]);
        break;
      }

      if (isRoot) {
        writeLines(["/", "<br>"]);
      } else {
        writeLines(["Permission not granted.", "<br>"]);
      }
      break;
    default:
      if (bareMode) {
        writeLines(["type 'help'", "<br>"]);
        break;
      }

      writeLines(DEFAULT);
      break;
  }
}

function writeLines(message: string[]) {
  message.forEach((item, idx) => {
    displayText(item, idx);
  });
}

function displayText(item: string, idx: number) {
  setTimeout(() => {
    if (!mutWriteLines) return;
    const p = document.createElement("p");
    p.innerHTML = item;
    mutWriteLines.parentNode!.insertBefore(p, mutWriteLines);
    scrollToBottom();
  }, 40 * idx);
}

function revertPasswordChanges() {
  if (!INPUT_HIDDEN || !PASSWORD) return;
  PASSWORD_INPUT.value = "";
  USERINPUT.disabled = false;
  INPUT_HIDDEN.style.display = "block";
  PASSWORD.style.display = "none";
  isPasswordInput = false;

  setTimeout(() => {
    USERINPUT.focus();
  }, 200);
}

function passwordHandler() {
  if (passwordCounter === 2) {
    if (!INPUT_HIDDEN || !mutWriteLines || !PASSWORD) return;
    writeLines([
      "<br>",
      "INCORRECT PASSWORD.",
      "PERMISSION NOT GRANTED.",
      "<br>",
    ]);
    revertPasswordChanges();
    passwordCounter = 0;
    return;
  }

  if (PASSWORD_INPUT.value === ROOT_PASSWORD) {
    if (!mutWriteLines || !mutWriteLines.parentNode) return;
    writeLines([
      "<br>",
      "PERMISSION GRANTED.",
      "Try <span class='command'>'rm -rf'</span>",
      "<br>",
    ]);
    revertPasswordChanges();
    isRoot = true;
    return;
  } else {
    PASSWORD_INPUT.value = "";
    passwordCounter++;
  }
}

function easterEggStyles() {
  const bars = document.getElementById("bars");
  const body = document.body;
  const main = document.getElementById("main");
  const span = document.getElementsByTagName("span");

  if (!bars) return;
  bars.innerHTML = "";
  bars.remove();

  if (main) main.style.border = "none";

  body.style.backgroundColor = "black";
  body.style.fontFamily = "VT323, monospace";
  body.style.fontSize = "20px";
  body.style.color = "white";

  for (let i = 0; i < span.length; i++) {
    span[i].style.color = "white";
  }

  USERINPUT.style.backgroundColor = "black";
  USERINPUT.style.color = "white";
  USERINPUT.style.fontFamily = "VT323, monospace";
  USERINPUT.style.fontSize = "20px";
  if (PROMPT) PROMPT.style.color = "white";
}

const initEventListeners = () => {
  if (HOST) {
    HOST.innerText = command.hostname;
  }

  if (USER) {
    USER.innerText = command.username;
  }

  if (PRE_HOST) {
    PRE_HOST.innerText = command.hostname;
  }

  if (PRE_USER) {
    PRE_USER.innerText = command.username;
  }

  window.addEventListener("load", () => {
    writeLines(BANNER);
  });

  USERINPUT.addEventListener("keypress", userInputHandler);
  USERINPUT.addEventListener("keydown", userInputHandler);
  PASSWORD_INPUT.addEventListener("keypress", userInputHandler);

  window.addEventListener("click", () => {
    USERINPUT.focus();
  });

  console.log(
    `%cPassword: ${command.password}`,
    "color: red; font-size: 20px;"
  );
};

initEventListeners();
