import { Conductor } from "./conductor";

export class Renderer {
  timeIndicator;
  currStaveNumber;
  numStaves;
  sheetWindow;
  eventCanvas;
  ctx;
  canvasWidth;
  canvasHeight;
  iconCache = []; // stores drawn icons
  imageCache = new Map(); // for memoizing loaded images

  constructor() {
    this.numStaves = 6;
    this.currStaveNumber = 1;

    this.timeIndicator = document.querySelector("#time-indicator");
    this.sheetWindow = document.getElementById("music-window");

    // Setup canvas
    this.eventCanvas = document.getElementById("event-canvas");
    this.ctx = this.eventCanvas.getContext("2d");

    this.resizeCanvas();
    window.addEventListener("resize", () => {
      this.resizeCanvas();
      this.redrawIcons();
    });

    this.timeIndicator.addEventListener("animationiteration", () => {
      this.currStaveNumber++;
      if (this.currStaveNumber > this.numStaves) {
        this.cleanUpAndRestart();
      }
    });

    // Render stave SVGs
    for (let i = 1; i <= this.numStaves; i++) {
      const staveWrapper = document.createElement("div");
      staveWrapper.classList.add("stave-wrapper");
      staveWrapper.setAttribute("id", `stave-wrapper-${i}`);
      staveWrapper.style.position = "relative";

      const staveObject = document.createElement("object");
      staveObject.type = "image/svg+xml";
      staveObject.data = "assets/svg/stave.svg";
      staveObject.classList.add("stave-svg");

      staveWrapper.appendChild(staveObject);
      this.sheetWindow.appendChild(staveWrapper);
    }
  }

  resizeCanvas() {
    this.canvasWidth = this.sheetWindow.offsetWidth;
    this.canvasHeight = this.sheetWindow.offsetHeight;
    this.eventCanvas.width = this.canvasWidth;
    this.eventCanvas.height = this.canvasHeight;
  }

  async placeIcon(instrument) {
    if (this.currStaveNumber > this.numStaves) this.currStaveNumber = 1;

    const targetWrapper = document.getElementById(
      `stave-wrapper-${this.currStaveNumber}`
    );
    const rect = this.timeIndicator.getBoundingClientRect();
    const sheetLeft = this.sheetWindow.getBoundingClientRect().left;
    const xPosition = rect.left + window.scrollX - sheetLeft;

    const newObject = document.createElement("div");
    newObject.classList.add("event-icon");
    newObject.style.position = "absolute";
    newObject.style.left = `${xPosition}px`;
    newObject.style.top = instrument.yPos;
    newObject.style.width = instrument.width;
    newObject.style.height = instrument.height;

    // ✅ Detect and decode base64 if needed
    let svgString = instrument.image;
    if (svgString.startsWith("data:image/svg+xml;base64,")) {
      const base64 = svgString.split(",")[1];
      svgString = atob(base64);
    }

    const parser = new DOMParser();
    const svgDoc = parser.parseFromString(svgString, "image/svg+xml");
    const svgElement = svgDoc.documentElement;

    // ✅ Handle parsing error
    if (svgElement.nodeName === "parsererror") {
      console.error("Failed to parse SVG:", svgString);
      return;
    }

    svgElement.style.width = "100%";
    svgElement.style.height = "100%";

    newObject.appendChild(svgElement);
    targetWrapper.appendChild(newObject);
  }

  async loadImageFromSVG(svgString) {
    if (this.imageCache.has(svgString)) {
      return this.imageCache.get(svgString);
    }

    return new Promise((resolve) => {
      const blob = new Blob([svgString], { type: "image/svg+xml" });
      const url = URL.createObjectURL(blob);
      const img = new Image();

      img.onload = () => {
        URL.revokeObjectURL(url); // clean up after load
        this.imageCache.set(svgString, img);
        resolve(img);
      };

      img.src = url;
    });
  }

  redrawIcons() {
    this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
    this.iconCache.forEach(({ image, x, y }) => {
      this.ctx.drawImage(image, x, y, 24, 24); // Adjust size as needed
    });
  }

  cleanUpAndRestart(reload = false) {
    this.iconCache = [];
    this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
    this.currStaveNumber = 1;

    Conductor.setTitle();
    if (reload) location.reload();
  }
}

// This will need to be worked on. There is no need for the loadImageFromSVG function here and the placeIcon function will need to be changed to reflect it.
// image size and z-index isn't correct and the canvas will need to be enlarged to allow icons to overhang the staves.
