// server and discord in one

import { Client, Events, GatewayIntentBits } from "npm:discord.js";
import { createCanvas } from "https://deno.land/x/canvas/mod.ts";
import { contentType } from "https://deno.land/std@0.202.0/media_types/mod.ts";

import config from "./config.json" with { type: "json" };

type Message = { author: string; content: string; id: string };

const kv = await Deno.openKv();

let messages = (await kv.get<Message[]>(["messages"])).value ?? [];

const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.MessageContent,
  ],
});

client.once(Events.ClientReady, (c) => {
  console.log(`logged in as ${c.user.tag}`);
});

client.login(config.token);

// we don't need to await!
function update_messages() {
  kv.set(["messages"], messages);
}

function add_message(msg: Message) {
  messages.push(msg);
  update_messages();
}

function delete_message(id: string) {
  messages = messages.filter((m) => m.id != id);
  update_messages();
}

client.on(Events.MessageCreate, (message) => {
  if (message.channel.name != "effector") return;
  add_message({
    author: message.author.username,
    content: message.content,
    id: message.id,
  });
  console.log("added", messages);
});

client.on(Events.MessageDelete, (message) => {
  delete_message(message.id);
  console.log("deleted", message.id, messages);
});

const canvas = createCanvas(1025, 612);
const ctx = canvas.getContext("2d");

const default_fill = "#3B0920";
const bg_fill = "#FFE8D4";
const border_stroke = "#83254F";

function clear_canvas() {
  ctx.fillStyle = bg_fill;
  ctx.strokeStyle = border_stroke;
  ctx.lineWidth = 10;
  ctx.fillRect(0, 0, 1025, 612);
  ctx.strokeRect(0, 0, 1025, 612);
}

function draw_message(x: number, y: number, message: Message) {
  ctx.fillStyle = "#FFAB5C";
  ctx.fillText(message.author, x, y);
  ctx.fillStyle = default_fill;
  console.log(message);
  ctx.fillText(
    message.content == "" ? "[empty message]" : message.content,
    x + ctx.measureText(message.author).width + 5,
    y,
  );
}

Deno.serve({ port: 61263 }, () => {
  const most_recent = messages.slice(-40);

  clear_canvas();

  most_recent.forEach((msg, i) => {
    draw_message(13, 17 + i * 15, msg);
  });

  return new Response(canvas.toBuffer(), {
    headers: { "Content-Type": contentType("png") },
  });
});