// number of messages to load at once when clicking "load more"
const MESSAGE_LOAD_LIMIT = 150;
const BASE_TITLE = document.title;

let currentChannel;
//image file formats which can be rendered in browser
let imageFormats = [
  "bmp",
  "gif",
  "ico",
  "jpeg",
  "jpe",
  "jpg",
  "jfif",
  "apng",
  "png",
  "tga",
  "tiff",
  "tif",
  "svg",
  "webp",
];

const loadMessages = async (channelId, skip = 0, initial = false) => {
  let channelEl = document.getElementById(`channel-${channelId}`);
  // hack to avoid loading the same messages repeatedly if clicking the channel repeatedly without switching
  if (channelEl.classList.contains("channel-active") && skip == 0) return;
  Array.from(document.querySelectorAll(".channel-active")).forEach(ch => {
    ch.classList.remove("channel-active");
  });
  channelEl.classList.add("channel-active");
  window.location.hash = channelId;

  document.title = `${channelEl.children[0].textContent} | ${BASE_TITLE}`;

  const messages = document.getElementById("messages");
  const prevHeight = Array.from(messages.children).reduce((accumulator, element) => accumulator + element.offsetHeight, 0);
  const loadButton = document.getElementById("load-more-button");
  if (loadButton) {
    loadButton.outerHTML = "";
  }
  if (currentChannel !== channelId) messages.innerHTML = "";
  currentChannel = channelId;
  const channelData = await fetch(
    `/api/v1/discord/channel/${channelId}?o=${skip}`
  ).then(resp => resp.json());
  channelData.map((msg) => {
    let dls = "";
    let avatarurl = "";
    let embeds = "";
    if (msg.content) {
      msg.content = msg.content
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/"/g, "&quot;")
        .replace(/<br \/>/g, "");

      // XXX scanning for &lt; here because < was encoded—not really ideal
      // the a? is because animated emojis are <a:[emoji name]:[emoji id]>
      msg.content = msg.content.replace(/&lt;a?:(.+?):(\d+)>/g, '<img class="emoji" title=":$1:" src="https://cdn.discordapp.com/emojis/$2">');
    }
    msg.attachments.map((dl) => {
      if (imageFormats.includes(dl.name.split(".").pop())) {
        dls += `<a href="/data/${dl.path}?f=${dl.name}" target="_blank"><img class="user-post-image" style="max-width:300px" src="/thumbnail/data${dl.path}" data-tries="2" onerror="if(this.dataset['tries']!='0'){this.src='/data/${dl.path}?f=${dl.name}';this.dataset['tries']--;}"></a><br>`;
      } else {
        dls += `<a href="/data/${dl.path}?f=${dl.name}">Download ${dl.name
          .replace(/&/g, "&amp;")
          .replace(/</g, "&lt;")
          .replace(/"/g, "&quot;")}</a><br>`;
      }
    });
    msg.embeds.map((embed) => {
      // XXX this is almost definitely wrong
      embeds += `
        <a href="/data/${embed.url}" target="_blank">
          <div class="embed-view" style="max-width:300px">
            <p>${(embed.description || embed.title || "")
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/"/g, "&quot;")}</p>
          </div>
        </a>
      `;
    });
    if (msg.author.avatar) {
      avatarurl = `https://cdn.discordapp.com/avatars/${msg.author.id}/${msg.author.avatar}`;
    } else {
      avatarurl = "/static/discordgrey.png";
    }

    messages.innerHTML = `
      <div class="message">
        <div class="avatar">
          <img class="avatar" src="${avatarurl}" onerror="this.src = '/static/discordgrey.png'" referrerpolicy="no-referrer" alt="">
        </div>
        <div style="display:inline-block" id="${msg.id}">
          <div class="message-header">
            <b><p>${msg.author.username.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/"/g, "&quot;")}</p></b>
            <p style="color:#757575">${new Date(msg.published)}</p>
          </div>
          <p><pre class="message__body">${msg.content}</pre></p>
          ${dls}
          ${embeds}
        </div>
      </div>
    ` + messages.innerHTML;
  });

  // avoid adding the button if there are no more messages
  if (channelData.length == MESSAGE_LOAD_LIMIT) {
    messages.innerHTML = `
      <div class="message" id="load-more-button">
        <button onClick="loadMessages('${channelId}', ${skip + MESSAGE_LOAD_LIMIT})" class="load-more-button">
          Load More
        </button>
      </div>
    ` + messages.innerHTML;
  } else {
    messages.innerHTML = `
      <div class="message" id="load-more-button">
        <p>End of channel history</p>
      </div>
    ` + messages.innerHTML;
  }

  messages.scrollTop = messages.scrollHeight - prevHeight;
};

const load = async () => {
  const pathname = window.location.pathname.split("/");
  const serverData = await fetch(`/api/v1/discord/channel/lookup/${pathname[3]}`);
  const server = await serverData.json();
  const channels = document.getElementById("channels");
  server.forEach((ch) => {
    const channel = document.getElementById(`channel-${ch.id}`);
    if (!channel) {
      channels.innerHTML += `
        <div class="channel" id="channel-${ch.id}" onClick="loadMessages('${ch.id}')">
          <p>#${ch.name.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/"/g, "&quot;")}</p>
        </div>
      `;
    }
  });

  const serverID = window.location.href.match(/\/discord\/server\/(\d+)/)[1];

  channels.innerHTML += `
    <div class="channel" id="linked-accounts" style="position: fixed; bottom: 0;">
      <a href="/discord/user/${serverID}/links">Linked Accounts</a>
    </div>
  `;

  if (window.location.hash !== "") {
    loadMessages(window.location.hash.slice(1).split("-")[0]);
  }
};

load();
