import {
  createAttachmentURL,
  createDiscordChannelPageURL,
  createThumbnailURL,
} from "#lib/urls";
import { FancyLink, KemonoLink } from "#components/links";
import { IDiscordAttachment, IDiscordChannelMessage } from "./types";

import * as styles from "./discord.module.scss";

interface IProps {
  serverID: string;
  channelID: string;
  messages: IDiscordChannelMessage[];
  offset?: number;
}

interface IDiscordMessageProps {
  message: IDiscordChannelMessage;
}

const MESSAGE_LOAD_LIMIT = 150;
const imageFormats = [
  "bmp",
  "gif",
  "ico",
  "jpeg",
  "jpe",
  "jpg",
  "jfif",
  "apng",
  "png",
  "tga",
  "tiff",
  "tif",
  "svg",
  "webp",
];

export function DiscordMessages({
  serverID,
  channelID,
  messages,
  offset,
}: IProps) {
  return (
    <ul className={styles.messages}>
      <li>
        {messages.length !== MESSAGE_LOAD_LIMIT ? (
          <p>End of channel history</p>
        ) : (
          <KemonoLink
            url={String(
              createDiscordChannelPageURL(
                serverID,
                channelID,
                !offset ? MESSAGE_LOAD_LIMIT : offset + MESSAGE_LOAD_LIMIT
              )
            )}
          >
            Load More
          </KemonoLink>
        )}
      </li>

      {messages.map((message) => (
        <DiscordMessage message={message} />
      ))}
    </ul>
  );
}

function DiscordMessage({ message }: IDiscordMessageProps) {
  const { id, author, content, published, attachments, embeds } = message;
  const avatarURL = author.avatar
    ? `https://cdn.discordapp.com/avatars/${author.id}/${author.avatar}`
    : "/static/discordgrey.png";

  // react automatically escapes outside of `dangerouslySetInnerHTML`
  return (
    <li className={styles.message}>
      <div id={id}>
        <div className={styles.header}>
          <div className={styles.avatar}>
            <img
              className={styles.avatar}
              src={avatarURL}
              onError={(event) =>
                (event.currentTarget.src = "/static/discordgrey.png")
              }
              referrerPolicy="no-referrer"
              alt=""
            />
          </div>
          <p className={styles.username}>
            <b>{author.username}</b>
          </p>

          <p className={styles.published}>{String(new Date(published))}</p>
        </div>

        <p>
          <pre className={styles.body}>{content}</pre>
        </p>

        {attachments.map((attachment) => (
          <Attachment attachment={attachment} />
        ))}

        {embeds.map(({ url, title, description }) => (
          <FancyLink url={url} className={styles.embed}>
            {description ?? title ?? ""}
          </FancyLink>
        ))}
      </div>
    </li>
  );
}

interface IAttachmentProps {
  attachment: IDiscordAttachment;
}

function Attachment({ attachment }: IAttachmentProps) {
  const { name, path } = attachment;
  const extension = name.split(".").pop() ?? "";
  const url = String(createAttachmentURL(path, name));
  const thumbnailURL = String(createThumbnailURL(path));

  return (
    <>
      {!imageFormats.includes(extension) ? (
        <a href={url}>Download {name}</a>
      ) : (
        <a className="image-link" href={url} target="_blank">
          <img
            className={styles.image}
            src={thumbnailURL}
            data-tries="2"
            onError={(event) => {
              const img = event.currentTarget;
              const tries = Number(img.dataset.tries);

              if (tries === 0) {
                return;
              }

              img.src = url;

              img.dataset.tries = String(tries - 1);
            }}
          />
        </a>
      )}
      <br />
    </>
  );
}
