const sendButton = document.querySelector("button#send");
const username =
  new URLSearchParams(window.location.search).get("u") || "Anonymous";

const isStreamMode = new URLSearchParams(window.location.search).get("stream") === "1";
if (isStreamMode) {
  document.body.classList.add("stream-mode");
}

sendButton.addEventListener("click", send);

let cooldownTime = 0;
let cooldownInterval = null;

function send() {
  if (cooldownTime > 0) return;
  const messageText = window.getCurrentText ? window.getCurrentText() : "";
  let data = canvas.toDataURL("image/png");

  // Crop white space top and bottom if there's no text preventing it
  if (!messageText || messageText.trim() === "") {
    const ctx = canvas.getContext("2d");
    const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const data32 = new Uint32Array(imgData.data.buffer);

    let top = canvas.height;
    let bottom = -1;

    for (let y = 0; y < canvas.height; y++) {
      let rowHasPixel = false;
      for (let x = 0; x < canvas.width; x++) {
        const p = data32[y * canvas.width + x];
        // ABGR: 0xFFFFFFFF is white. 0x00000000 is transparent.
        if (p !== 0xFFFFFFFF && p !== 0) {
          rowHasPixel = true;
          break;
        }
      }
      if (rowHasPixel) {
        if (y < top) top = y;
        if (y > bottom) bottom = y;
      }
    }

    if (top <= bottom) {
      // Add a little padding
      const padding = 10;
      top = Math.max(0, top - padding);
      bottom = Math.min(canvas.height - 1, bottom + padding);

      const cropHeight = bottom - top + 1;
      const tempCanvas = document.createElement("canvas");
      tempCanvas.width = canvas.width;
      tempCanvas.height = cropHeight;
      const tempCtx = tempCanvas.getContext("2d");
      tempCtx.putImageData(ctx.getImageData(0, top, canvas.width, cropHeight), 0, 0);
      data = tempCanvas.toDataURL("image/png");
    } else {
      // Canvas is entirely white/blank
      const tempCanvas = document.createElement("canvas");
      tempCanvas.width = canvas.width;
      tempCanvas.height = 20; // extremely minimal height
      const tempCtx = tempCanvas.getContext("2d");
      tempCtx.fillStyle = "white";
      tempCtx.fillRect(0, 0, canvas.width, 20);
      data = tempCanvas.toDataURL("image/png");
    }
  }

  const payload = {
    from: username,
    text: messageText,
    doodle: data,
    color: userColor,
    timestamp: new Date().toISOString(),
  };
    fetch("/api/messages", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(payload),
    }).then(response => {
      if (response.status === 401) {
        window.location.href = "/";
      }
    });
  // clear canvas after sending
  if (window.resetCanvas) {
    window.resetCanvas();
  } else {
    canvas.width = canvas.width;
    window.clearCurrentText();
  }

  // start cooldown
  cooldownTime = 60;
  sendButton.disabled = true;
  sendButton.innerHTML = `wait ${cooldownTime}s`;
  
  cooldownInterval = setInterval(() => {
    cooldownTime--;
    if (cooldownTime <= 0) {
      clearInterval(cooldownInterval);
      sendButton.disabled = false;
      sendButton.innerHTML = "send";
    } else {
      sendButton.innerHTML = `wait ${cooldownTime}s`;
    }
  }, 1000);
}

function addToChatLog(msg) {
  const chatLog = document.getElementById("chat-log");

  const messageBox = document.createElement("div");
  messageBox.className = "message-box";

  if (msg.color && msg.color.startsWith('#')) {
    messageBox.style.borderColor = msg.color;
    messageBox.style.boxShadow = `0 4px 12px ${msg.color}33`;
  } else {
    messageBox.classList.add(`accent-${msg.color}`);
  }

  const messageHeader = document.createElement("div");
  messageHeader.className = "message-header";
  if (msg.color && msg.color.startsWith('#')) {
    messageHeader.style.color = msg.color;
    messageHeader.style.borderBottomColor = msg.color;
  }

  const usernameSpan = document.createElement("span");
  usernameSpan.className = "username";
  usernameSpan.textContent = msg.from;

  messageHeader.appendChild(usernameSpan);
  messageBox.appendChild(messageHeader);

  const canvasDiv = document.createElement("div");
  canvasDiv.className = "chat-canvas";

  const messageTextSpan = document.createElement("span");
  messageTextSpan.className = "message-text";
  messageTextSpan.innerHTML = msg.text.replace(/\n/g, "<br>");

  canvasDiv.appendChild(messageTextSpan);

  if (msg.doodle) {
    const img = document.createElement("img");
    img.src = msg.doodle;
    canvasDiv.appendChild(img);
  }

  messageBox.appendChild(canvasDiv);

  animatePreviousMessages(chatLog, false);

  chatLog.insertBefore(messageBox, chatLog.firstChild);
}

function addSystemMessageToChatLog(content) {
  const chatLog = document.getElementById("chat-log");

  const messageBox = document.createElement("div");
  messageBox.className = "system-message-box";
  messageBox.innerHTML = content;

  animatePreviousMessages(chatLog, true);

  chatLog.insertBefore(messageBox, chatLog.firstChild);
}

function animatePreviousMessages(chatLog, newIsSystem) {
  const previousMessages = chatLog.querySelectorAll(
    ".message-box, .system-message-box"
  );

  previousMessages.forEach((message) => {
    const prevIsSystem = message.classList.contains("system-message-box");
    const startTranslate = prevIsSystem
      ? newIsSystem
        ? "translateY(calc(100% + 5px))"
        : "translateY(calc(500% + 5px))"
      : newIsSystem
      ? "translateY(calc(20% + 5px))"
      : "translateY(calc(100% + 5px))";

    message.animate(
      [{ transform: startTranslate }, { transform: "translateY(0%)" }],
      {
        duration: 100,
        easing: "linear",
        fill: "forwards",
      }
    );
  });
}

// run when a new message is received from the server
function handleMessage(msg) {
  const data = JSON.parse(msg);
  if (data.type === "system") {
    addSystemMessageToChatLog(data.content);
    return;
  }
  addToChatLog(data);
}

// listens for new messages from the server
async function listen() {
  try {
    const url = isStreamMode ? "/api/messages?stream=1" : "/api/messages";
    const response = await fetch(url);
    if (response.status === 401 && !isStreamMode) {
      window.location.href = "/";
      return;
    }
    if (response.status === 200) {
      const msg = await response.text();
      handleMessage(msg);
    }
  } catch (err) {
    console.error("error listening messages:", err);
  } finally {
    // goes back to listening just after receiving a message or on error
    setTimeout(listen, 50); // small delay to avoid stack overflow
  }
}

// load backlog first, then start listening
async function loadBacklog() {
  try {
    const url = isStreamMode ? "/api/backlog?stream=1" : "/api/backlog";
    const response = await fetch(url);
    if (response.status === 401 && !isStreamMode) {
      window.location.href = "/";
      return;
    }
    if (response.status === 200) {
      const messages = await response.json();
      // append chronologically
      for (const msg of messages) {
        if (msg.type === "system") {
          addSystemMessageToChatLog(msg.content);
        } else {
          addToChatLog(msg);
        }
      }
    }
  } catch (err) {
    console.error("error loading backlog:", err);
  }
}

// start listening for messages right after loading the app backlog
loadBacklog().then(() => listen());

// sets the username label in the user message box
const usernameLabel = document.querySelector(
  "#user-message-box > .message-header > .username"
);
usernameLabel.innerHTML = username;
