import { fileToDataURL } from "../../util";
import { AvatarOptions, squareImageAvatar } from "./avatar";
import { CanvasLayer, drawLayer } from "./Layers";

export type Ctx = CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;
export type TemplateRenderFunction = (options: AvatarOptions) => CanvasLayer[];

/**
 * Generates a canvas that contains the generated image.
 */
async function generateCanvas(
  layers: CanvasLayer[],
  width: number,
  height: number
) {
  const canvas = window["OffscreenCanvas"]
    ? new OffscreenCanvas(width, height)
    : document.createElement("canvas");
  canvas.width = width;
  canvas.height = height;

  const ctx: Ctx = canvas.getContext("2d");

  for (const layer of layers) {
    await drawLayer(ctx, layer, width, height);
  }

  return canvas;
}

export async function clientBuildImageUrl(
  file: File,
  width: number,
  height: number,
  borderWidth: number,
  zoomFactor: number,
  templateUrl: string,
  templateRenderFunction: TemplateRenderFunction = squareImageAvatar
) {
  const uploadDataUrl = await fileToDataURL(file);

  const layers: CanvasLayer[] = templateRenderFunction({
    width,
    height,
    borderWidth,
    template: templateUrl,
    src: uploadDataUrl,
    srcRotation: 1,
    srcOffsetX: 0,
    srcOffsetY: 0,
    zoomFactor,
  });

  const canvas = await generateCanvas(layers, width, height);
  let url = "";
  if (canvas instanceof HTMLCanvasElement) {
    if (canvas.toBlob) {
      console.debug("Create Url via HTMLCanvasElement.toBlob");
      const blob = await new Promise(resolve => canvas.toBlob(resolve, "image/png"));
      url = URL.createObjectURL(blob);
    } else {
      // Fallback for Internet Explorer, might not work as the data url can become quite long
      console.debug("Create Url via HTMLCanvasElement.toDataURL");
      url = canvas.toDataURL("image/png");
    }
  } else {
    console.debug("Create Url via OffscreenCanvas.convertToBlob");
    const blob = await canvas.convertToBlob();
    url = URL.createObjectURL(blob);
  }

  return url;
}
