import {
  Application,
  Container,
  FederatedPointerEvent,
  Graphics,
  Rectangle,
  Sprite,
} from "pixi.js";

async function setup(app: Application) {
  await app.init({ background: "#111111", resizeTo: window, antialias: true });
  document.getElementById("pixi-container")!.appendChild(app.canvas);
}

function makeCyanPointer(): Graphics {
  const size = 20;
  const height = (Math.sqrt(3) / 2) * size;
  const g = new Graphics();
  g.fill(0x00ffff);
  g.moveTo(0, (-height * 2) / 3);
  g.lineTo(-size / 2, height / 3);
  g.lineTo(size / 2, height / 3);
  g.closePath();
  g.fill();
  return g;
}

function addBoxes(app: Application): void {
  const cx = app.screen.width / 2;
  const cy = app.screen.height / 2;
  const size = 320;

  const redBox = new Graphics();
  redBox.rect(-size / 2, -size / 2, size, size);
  redBox.setStrokeStyle({ color: 0xff4444, width: 3 });
  redBox.stroke();
  redBox.hitArea = new Rectangle(-size / 2, -size / 2, size, size);
  redBox.x = cx - 220;
  redBox.y = cy;

  const greenBox = new Graphics();
  greenBox.rect(-size / 2, -size / 2, size, size);
  greenBox.setStrokeStyle({ color: 0x44ff88, width: 3 });
  greenBox.stroke();
  greenBox.hitArea = new Rectangle(-size / 2, -size / 2, size, size);
  greenBox.x = cx + 220;
  greenBox.y = cy;

  const texture = app.renderer.generateTexture(makeCyanPointer());

  // Red box: canvas-drawn sprite follows the cursor (native cursor hidden)
  const cyanPointer = new Sprite(texture);
  cyanPointer.anchor.set(0.5, 0.5);
  cyanPointer.visible = false;

  redBox.eventMode = "static";
  redBox.cursor = "none";
  redBox.on("pointerenter", () => {
    cyanPointer.visible = true;
  });
  redBox.on("pointerleave", () => {
    cyanPointer.visible = false;
  });

  // Green box: native cursor replaced with the same icon via CSS data URL
  const extractedCanvas = app.renderer.extract.canvas(texture);
  const dataURL = (extractedCanvas as HTMLCanvasElement).toDataURL("image/png");
  const hx = Math.round(texture.width / 2);
  const hy = 0;

  greenBox.eventMode = "static";
  greenBox.cursor = `url("${dataURL}") ${hx} ${hy}, default`;

  const world = new Container();
  world.eventMode = "static";
  world.hitArea = new Rectangle(-100000, -100000, 200000, 200000);
  world.addChild(redBox);
  world.addChild(greenBox);
  world.addChild(cyanPointer);
  app.stage.addChild(world);

  world.on("pointermove", (e: FederatedPointerEvent) => {
    const pos = e.getLocalPosition(world);
    cyanPointer.x = pos.x;
    cyanPointer.y = pos.y;
  });
}

(async () => {
  const app = new Application();
  await setup(app);
  addBoxes(app);
})();