<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Terminal</title>
    <style>
      html {
        font-family: arial;
      }
    </style>
    <link
      rel="stylesheet"
      href="https://unpkg.com/xterm@4.11.0/css/xterm.css"
    />
  </head>
  <body>
    <span style="font-size: 1.4em">Terminal</span>&nbsp;&nbsp;&nbsp;
    <span style="font-size: small"
      >status:
      <span style="font-size: small" id="status">connecting...</span></span
    >

    <div style="width: 100%; height: calc(100% - 50px)" id="terminal"></div>

    <p style="text-align: right; font-size: small">
      built by <a href="https://chadsmith.dev">Chad Smith</a>
      <a href="https://github.com/cs01">GitHub</a>
    </p>
    <!-- xterm -->
    <script src="https://unpkg.com/xterm@4.11.0/lib/xterm.js"></script>
    <script src="https://unpkg.com/xterm-addon-fit@0.5.0/lib/xterm-addon-fit.js"></script>
    <script src="https://unpkg.com/xterm-addon-web-links@0.4.0/lib/xterm-addon-web-links.js"></script>
    <script src="https://unpkg.com/xterm-addon-search@0.8.0/lib/xterm-addon-sear
ch.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.min.js"></script>

    <script>
      const term = new Terminal({
        cursorBlink: true,
        macOptionIsMeta: true,
        scrollback: true,
      });
      // https://github.com/xtermjs/xterm.js/issues/2941
      const fit = new FitAddon.FitAddon();
      term.loadAddon(fit);
      term.loadAddon(new WebLinksAddon.WebLinksAddon());
      term.loadAddon(new SearchAddon.SearchAddon());

      term.open(document.getElementById("terminal"));
      fit.fit();
      term.resize(15, 50);
      console.log(`size: ${term.cols} columns, ${term.rows} rows`);
      fit.fit();
      term.writeln("Welcome, {{ current_user.username }}");
      term.writeln("Terminal");
      term.onData((data) => {
        console.log("key pressed in browser:", data);
        socket.emit("pty-input", { input: data });
      });

      const socket = io.connect("/pty");
      const status = document.getElementById("status");

      socket.on("pty-output", function (data) {
        console.log("new output received from server:", data.output);
        term.write(data.output);
      });

      socket.on("connect", () => {
        fitToscreen();
        status.innerHTML =
          '<span style="background-color: lightgreen;">connected</span>';
      });

      socket.on("disconnect", () => {
        status.innerHTML =
          '<span style="background-color: #ff8383;">disconnected</span>';
      });

      function fitToscreen() {
        fit.fit();
        const dims = { cols: term.cols, rows: term.rows };
        console.log("sending new dimensions to server's pty", dims);
        socket.emit("resize", dims);
      }

      function debounce(func, wait_ms) {
        let timeout;
        return function (...args) {
          const context = this;
          clearTimeout(timeout);
          timeout = setTimeout(() => func.apply(context, args), wait_ms);
        };
      }

      const wait_ms = 50;
      window.onresize = debounce(fitToscreen, wait_ms);
    </script>
  </body>
</html>
