import { Canvas, createCanvas, loadImage, SKRSContext2D } from "@napi-rs/canvas";
import {
  GenerateBattlerOptions,
  Colour,
  Opponents,
  PlayerActions,
} from "./types";

export const validColours = Object.entries(Colour).map((x) => x[0]);
export const validOpponents = Object.entries(Opponents).map((x) => x[0]);
export const validPlayerActions = Object.entries(PlayerActions).map((x) => x[1]);

export async function generateBattler(
  opts: GenerateBattlerOptions & { direction?: "right" | "left" },
): Promise<Canvas> {
  // Image dimensions
  const canvas = createCanvas(1280, 1280);
  const context = canvas.getContext("2d");
  if (!validColours.includes(opts.colour)) opts.colour = Colour.Black;

  // Load + draw the necessary images

  // [Glow]
  try {
    if (opts.glow && opts.glow !== "None") {
      const glow = await loadImage(`./assets/glows/${opts.glow}.png`);
      context.drawImage(glow, 0, 0, canvas.width, canvas.height);
    }
  } catch (err) { }

  // [Back]
  try {
    if (opts.back && opts.back !== "None") {
      const back = await loadImage(`./assets/backs/${opts.back}.png`)
      context.drawImage(back, 0, 0, canvas.width, canvas.height)
    }
  } catch (err) { }

  // [Base]
  const base = await loadImage(`./assets/bases/${opts.colour || "Black"}.png`);
  context.drawImage(base, 0, 0, canvas.width, canvas.height);

  // [Upper Bottom]
  try {
    if (opts.upperBottom && opts.upperBottom !== "None") {
      const face = await loadImage(`./assets/upperBottom/${opts.face}.png`);
      context.drawImage(face, 0, 0, canvas.width, canvas.height);
    }
  } catch (err) { }

  // [Bottom]
  try {
    if (opts.bottom && opts.bottom !== "None") {
      const bottom = await loadImage(`./assets/bottoms/${opts.bottom}.png`);
      context.drawImage(bottom, 0, 0, canvas.width, canvas.height);
    }
  } catch (err) { }

  // [Top]
  try {
    if (opts.top && opts.top !== "None") {
      const top = await loadImage(`./assets/tops/${opts.top}.png`);
      context.drawImage(top, 0, 0, canvas.width, canvas.height);
    }
  } catch (err) { }

  // [Face]
  try {
    if (opts.face && opts.face !== "None") {
      const face = await loadImage(`./assets/faces/${opts.face}.png`);
      context.drawImage(face, 0, 0, canvas.width, canvas.height);
    }
  } catch (err) { }

  // [Hair]
  try {
    if (opts.hair && opts.hair !== "None") {
      const face = await loadImage(`./assets/hair/${opts.hair}.png`);
      context.drawImage(face, 0, 0, canvas.width, canvas.height);
    }
  } catch (err) { }

  // [Hat]
  try {
    if (opts.hat && opts.hat !== "None") {
      const hat = await loadImage(`./assets/hats/${opts.hat}.png`);
      context.drawImage(hat, 0, 0, canvas.width, canvas.height);
    }
  } catch (err) { }

  // [Eyes]
  try {
    if (opts.eye && opts.eye !== "None") {
      const eye = await loadImage(`./assets/eyes/${opts.eye}.png`);
      context.drawImage(eye, 0, 0, canvas.width, canvas.height);
    }
  } catch (err) { }

  // [Upper Top]
  try {
    if (opts.upperTop && opts.upperTop !== "None") {
      const eye = await loadImage(`./assets/upperTop/${opts.upperTop}.png`);
      context.drawImage(eye, 0, 0, canvas.width, canvas.height);
    }
  } catch (err) { }

  // [Neck]
  try {
    if (opts.neck && opts.neck !== "None") {
      const neck = await loadImage(`./assets/necks/${opts.neck}.png`)
      context.drawImage(neck, 0, 0, canvas.width, canvas.height)
    }
  } catch (err) { }

  // [Buddy]
  try {
    if (opts.buddy && opts.buddy !== "None") {
      const buddy = await loadImage(`./assets/buddies/${opts.buddy}.png`)
      context.drawImage(buddy, 0, 0, canvas.width, canvas.height)
    }
  } catch (err) { }

  if (opts.direction && opts.direction == "left") {
    let flipped = createCanvas(1280, 1280);
    let flippedCtx = flipped.getContext("2d");

    flippedCtx.scale(-1, 1);
    flippedCtx.drawImage(canvas, -canvas.width, 0, canvas.width, canvas.height);

    return flipped;
  }

  return canvas;
}

export function drawText(pos: [number, number], text: string, colour: string, outline: { colour: string, width: number }, ctx: SKRSContext2D) {
  ctx.strokeStyle = outline.colour;
  ctx.lineWidth = outline.width;
  ctx.fillStyle = colour;

  ctx.strokeText(text, pos[0], pos[1])
  ctx.fillText(text, pos[0], pos[1])
}

export const applyText = (canvas: Canvas, text: string, width: number) => {
  const context = canvas.getContext('2d');

  // Declare a base size of the font
  let fontSize = 175;

  do {
    // Assign the font to the context and decrement it so it can be measured again
    context.font = `${fontSize -= 10}px Lilita One`;
    // Compare pixel width of the text to the canvas minus the approximate avatar size
  } while (context.measureText(text).width > width);

  // Return the result to use in the actual canvas
  return context.font;
};