import { Juego } from "./main";

export type Sprite = {
  getWidth: (juego: Juego<any>) => number;
  getHeight: (juego: Juego<any>) => number;
  draw: (
    juego: Juego<any>,
    x: number,
    y: number,
    spriteIndex?: number,
    flipped?: boolean
  ) => void;
  width: number;
  height: number;
};

// Sprites are image assets that have a grid of tiles to animate
export function loadSprite(
  img: HTMLImageElement,
  // Calculates the size of the sprite when rendering
  size:
    | { width: (juego: Juego<any>) => number }
    | { height: (juego: Juego<any>) => number },
  tileSize?: { width: number; height: number }
): Sprite {
  const width = tileSize ? tileSize.width : img.width;
  const height = tileSize ? tileSize.height : img.height;

  const rowSize = Math.floor(img.width / width);
  if (img.width / width !== rowSize) {
    console.warn(
      `The sprite grid for ${img.src} has extra space after rows, are you sure the width/height of each tile is right?`
    );
  }

  function getWidth(juego: Juego<any>) {
    return "width" in size
      ? size.width(juego)
      : (size.height(juego) * width) / height;
  }

  function getHeight(juego: Juego<any>) {
    return "height" in size
      ? size.height(juego)
      : (size.width(juego) * height) / width;
  }

  function draw(
    juego: Juego<any>,
    x: number,
    y: number,
    spriteIndex = 0,
    flipped = false
  ) {
    const drawHeight = getHeight(juego);
    const drawWidth = getWidth(juego);
    const tileX = spriteIndex % rowSize;
    const tileY = Math.floor(spriteIndex / rowSize);
    if (flipped) {
      juego.ctx.save();
      juego.ctx.scale(-1, 1);
      juego.ctx.drawImage(
        img,
        tileX * width,
        tileY * height,
        width,
        height,
        -x - drawWidth,
        y,
        drawWidth,
        drawHeight
      );
      juego.ctx.restore();
    } else {
      juego.ctx.drawImage(
        img,
        tileX * width,
        tileY * height,
        width,
        height,
        x,
        y,
        drawWidth,
        drawHeight
      );
    }
  }

  return { getWidth, getHeight, draw, width, height };
}
