import { FillerData } from "./FillerData";
import { FillerScene } from "./FillerScene";

/**
 * DOM overlay 手指提示层
 * - 页面初始化后 800ms 自动指向当前颜色组第一个待填区块中心
 * - 用户每次交互（点击填色/点击失败）后重置 2s 闲置计时器
 * - 全图填完后停止
 */
export class FingerHint {
  private el: HTMLDivElement;
  private idleTimer: number | null = null;
  private stopped = false;

  private static readonly IDLE_MS = 1500;
  /** 手指图片尺寸（CSS px） */
  private static readonly SIZE = 72;
  /**
   * 指尖在图片内的相对位置（0~1）。
   * finger.png 通常是食指斜向下指，指尖在图片左上角约 (25%, 12%)。
   */
  private static readonly TIP_X = 0.25;
  private static readonly TIP_Y = 0.12;

  constructor(
    private scene: FillerScene,
    private fillerData: FillerData,
    fingerUrl: string,
  ) {
    this.el = this.createEl(fingerUrl);
    document.body.appendChild(this.el);
    this.injectStyle();
  }

  // ─── 公开 API ──────────────────────────────────────────────────

  /** 初始化完成后调用，启动首次提示 */
  start() {
    this.scheduleHint(800);
  }

  /** 每次用户有交互动作（填色成功/失败）时调用 */
  onUserInteraction() {
    this.hide();
    if (!this.stopped) {
      this.scheduleHint(FingerHint.IDLE_MS);
    }
  }

  /** 当 fillerData.currentGroup 发生变化时，等待 2s 闲置后指向新 group */
  onGroupChange() {
    if (this.stopped) return;
    // 取消旧定时器，隐藏当前手势，重新等待 2s 闲置
    if (this.idleTimer !== null) {
      clearTimeout(this.idleTimer);
      this.idleTimer = null;
    }
    this.hide();
    this.scheduleHint(FingerHint.IDLE_MS);
  }

  /** 全图填完时调用 */
  stop() {
    this.stopped = true;
    this.hide();
    if (this.idleTimer !== null) {
      clearTimeout(this.idleTimer);
      this.idleTimer = null;
    }
  }

  // ─── 私有实现 ──────────────────────────────────────────────────

  private scheduleHint(delay: number) {
    if (this.idleTimer !== null) clearTimeout(this.idleTimer);
    this.idleTimer = window.setTimeout(() => this.showHint(), delay);
  }

  private showHint() {
    if (this.stopped) return;
    const group = this.fillerData.currentGroup;
    if (!group) return;
    const area = group.firstUncoloredArea;
    if (!area) return;

    const [cssX, cssY] = this.contentToScreen(area.center.x, area.center.y);
    this.show(cssX, cssY);
  }

  /**
   * 将内容坐标（图片像素空间）转换为 CSS 页面坐标（视口 px）
   *
   * Scene 的 userMat 是列主序矩阵，对简单 scale+translate 变换：
   *   physX = cx * mat[0] + cy * mat[4] + mat[12]
   *   physY = cx * mat[1] + cy * mat[5] + mat[13]
   * 再除以 devicePixelRatio 得到 canvas 内 CSS px；
   * 最后加上 canvas 元素的视口偏移，以匹配 position:fixed 坐标系。
   */
  private contentToScreen(cx: number, cy: number): [number, number] {
    const mat = this.scene.userMat;
    const ratio = this.scene.ratio;
    const physX = cx * mat[0] + cy * mat[4] + mat[12];
    const physY = cx * mat[1] + cy * mat[5] + mat[13];
    // canvas 内 CSS 像素
    const canvasCssX = physX / ratio;
    const canvasCssY = physY / ratio;
    // 加上 canvas 在视口中的偏移，转换为 position:fixed 坐标
    const canvas = this.scene.gl.canvas as HTMLElement;
    const rect = canvas.getBoundingClientRect();
    return [canvasCssX + rect.left, canvasCssY + rect.top];
  }

  private show(cssX: number, cssY: number) {
    const size = FingerHint.SIZE;
    // 将指尖对齐到目标坐标
    this.el.style.left = `${cssX - size * FingerHint.TIP_X}px`;
    this.el.style.top = `${cssY - size * FingerHint.TIP_Y}px`;
    this.el.style.display = "block";
    this.el.classList.add("finger-tapping");
  }

  private hide() {
    this.el.style.display = "none";
    this.el.classList.remove("finger-tapping");
  }

  private createEl(fingerUrl: string): HTMLDivElement {
    const size = FingerHint.SIZE;
    const el = document.createElement("div");
    el.id = "finger-hint";
    el.style.cssText = `
      position: fixed;
      width: ${size}px;
      height: ${size}px;
      pointer-events: none;
      z-index: 999;
      display: none;
      transform-origin: ${FingerHint.TIP_X * 100}% ${FingerHint.TIP_Y * 100}%;
    `;
    const img = document.createElement("img");
    img.src = fingerUrl;
    img.style.cssText = "width:100%;height:100%;object-fit:contain;";
    img.draggable = false;
    el.appendChild(img);
    return el;
  }

  private injectStyle() {
    if (document.getElementById("finger-hint-style")) return;
    const style = document.createElement("style");
    style.id = "finger-hint-style";
    style.textContent = `
      @keyframes finger-tap {
        0%   { transform: scale(1)    translateY(0);   opacity: 1;   }
        35%  { transform: scale(0.88) translateY(10px); opacity: 1;  }
        55%  { transform: scale(0.88) translateY(10px); opacity: 1;  }
        80%  { transform: scale(1)    translateY(0);   opacity: 1;   }
        100% { transform: scale(1)    translateY(0);   opacity: 1;   }
      }
      #finger-hint.finger-tapping {
        animation: finger-tap 1s ease-in-out infinite;
      }
    `;
    document.head.appendChild(style);
  }
}
