import { BgLayer, BgType } from "../base/BgLayer";
import { BorderLayer } from "../base/BorderLayer";
import { BoxLayer } from "../base/BoxLayer";
import { DebugLayer } from "../base/DebugLayer";
import { FrameLayer } from "../base/FrameLayer";
import { TouchTracker } from "../base/Gesture";
import { ImageShaders } from "../base/ImageShaders";
import { Padding, Scene } from "../base/Scene";
import { TextureLayer } from "../base/TextureLayer";
import { loadImage } from "../base/utils";
import AudioPlayer, { AudioType } from "./Audio";
import { AreaGroup, AreaGroups, Color, Settings } from "./common";
import Explosion from "./explosion";
import {
  FillerConfig,
  FillerData,
  FillerResource,
  FillerCallback,
} from "./FillerData";
import { FillerScene } from "./FillerScene";
import { HintLayer } from "./HintLayer";
import { LineArtLayer } from "./LineArtLayer";
import { NumberLayer } from "./NumberLayer";
import { WorkLayer } from "./WorkLayer";
import { LoadingController } from "./LoadingController";
import { FingerHint } from "./FingerHint";
import JSConfetti from "js-confetti";
import { initCta, ctaHighlight } from "./cta";
import { initAdPlatform } from "./mraid";

// 静态导入资源，Vite 构建时会将它们转为 data URI 内联进 HTML
import configRaw from "/assets/res/6a18f7d9957ac783bad75479/config.json?raw";
import pageUrl from "/assets/res/6a18f7d9957ac783bad75479/page.png?url";
import mapUrl from "/assets/res/6a18f7d9957ac783bad75479/map.png?url";
import specialUrl from "/assets/res/6a18f7d9957ac783bad75479/special.jpeg?url";
import numberFontUrl from "/assets/fonts/numbers_roboto_500.png?url";
import fingerUrl from "/assets/img/finger.png?url";
import logoUrl from "/assets/img/logo.png?url";
import logoTxtUrl from "/assets/img/logo-txt.png?url";
import coloringPagesUrl from "/assets/img/coloring-pages.png?url";
import slogonUrl from "/assets/img/slogon.png?url";

document.body.onload = function () {
  initCta();
  init();
};

async function test() {
  let canvas = document.querySelector("#canvas") as HTMLCanvasElement;
  canvas.width = canvas.clientWidth * window.devicePixelRatio;
  canvas.height = canvas.clientHeight * window.devicePixelRatio;
  let resource = await loadResource();
  let ctx = canvas.getContext("2d")!;
  ctx.fillStyle = "red";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(resource.page, 0, 0);
}

async function init() {
  const loadingController = new LoadingController({
    minDisplayTime: 1000, // 最小显示时间1秒
    fadeDuration: 300, // 淡出动画300ms
  });

  loadingController.show();

  let canvas = document.querySelector("#canvas") as HTMLCanvasElement;
  let gl = canvas.getContext("webgl2", {
    premultipliedAlpha: false,
  }) as WebGL2RenderingContext;
  let pixelRatio = window.devicePixelRatio;

  /** 根据 game-area 的实际渲染尺寸同步 canvas 像素尺寸 */
  function syncCanvasSize() {
    const gameArea = document.getElementById("game-area")!;
    const w = Math.round(gameArea.clientWidth * pixelRatio);
    const h = Math.round(gameArea.clientHeight * pixelRatio);
    if (canvas.width !== w || canvas.height !== h) {
      canvas.width = w;
      canvas.height = h;
      scene?.updateViewport();
    }
  }

  canvas.width = canvas.clientWidth * pixelRatio;
  canvas.height = canvas.clientHeight * pixelRatio;
  let scene = new FillerScene(gl, pixelRatio);

  // 确保 canvas 像素尺寸与实际 flex 布局一致（body.onload 时 dvh 可能还未最终结算）
  syncCanvasSize();

  let audio = new AudioPlayer();

  // 加载设置项，学个新语法 ...
  let settings: Settings = {
    hintStyle: "default",
    sound: true,
    vibrate: true,
    autoNext: true,
  };

  window.addEventListener("resize", () => syncCanvasSize());
  document
    .querySelector("#toggleTestLayer")
    ?.addEventListener("click", () => scene.toggleTestLayer());

  document.addEventListener("click", (e: MouseEvent) => onDocumentClick(e));
  document.addEventListener("touchstart", (e: TouchEvent) =>
    onDocumentClick(e),
  );

  let resource = await loadResource();

  loadingController.hide();
  initAdPlatform();

  // 设置固定顶栏 logo（图标 + 文字）
  (document.getElementById("app-logo") as HTMLImageElement).src = logoUrl;
  (document.getElementById("app-logo-txt") as HTMLImageElement).src =
    logoTxtUrl;

  // 预加载 promo 图片，避免动画播放时图片刚加载导致布局跳变
  (document.getElementById("promo-coloring") as HTMLImageElement).src =
    coloringPagesUrl;
  (document.getElementById("promo-slogon") as HTMLImageElement).src = slogonUrl;

  let taskList: number[] = [];

  // fingerHint 先声明，init 末尾赋值后回调中就能使用
  let fingerHint: FingerHint | null = null;

  let fillerData = new FillerData(
    new FillerConfig(settings),
    resource,
    gl,
    taskList,
    {
      onFillFailed() {
        console.log("填充失败");
        fingerHint?.onUserInteraction();
      },
      onFillSuccess() {
        console.log("填充成功");
        fingerHint?.onUserInteraction();
        if (fillerData.config.settings.vibrate) {
          vibrate();
        }
        cssAdjustProgress(fillerData.data.coloredPercent);
        cssSetColorProgress(
          fillerData.currentGroupIndex,
          fillerData.currentGroup!.progressPercent,
        );
        if (fillerData.currentGroup?.isAllColored) {
          if (fillerData.config.settings.sound) {
            audio.playAudio(AudioType.ColorDone);
          }
          cssColorDone(fillerData);
        }
      },
      onSwitchGroup() {
        let currentGroupIndex = fillerData.currentGroupIndex;
        console.log(`切换到下一个group ${currentGroupIndex}`);
        cssSelectColor(currentGroupIndex);
        cssAdjustScroll(fillerData);
      },
      onFinish() {
        fingerHint?.stop();
        cssOnFinish(scene, workLayer, hintLayer, audio);
      },
    },
  );

  scene.fillerData = fillerData;

  console.log("resource", resource);

  // canvas 区域与所有 UI 完全分离，只保留极小视觉边距
  scene.setContentPadding(new Padding(20, 20, 20, 20));

  //let page = await loadImage('/webgl/page.png')
  //let page = await loadImage('/assets/resources/friend/page_gray.png')

  let width = fillerData.width;
  let height = fillerData.height;
  scene.setContentSize(width, height);

  // // 最底层：透明背景，canvas 透出 body 渐变色，与整体 UI 融为一体
  // scene.addLayer(new BackgroundLayer(scene, scene.width, scene.height, [0, 0, 0, 0]));

  if (resource.bg) {
    scene.addLayer(
      new BgLayer(scene, resource.bg, scene.width, scene.height, BgType.Repeat),
    );
  }
  scene.addLayer(new BoxLayer(scene, 0, 0, width, height));

  let hintLayer = new HintLayer(scene, fillerData);
  scene.addLayer(hintLayer);
  scene.addLayer(new NumberLayer(scene, resource.numberImage, fillerData, 1));

  let workLayer = new WorkLayer(scene, fillerData);

  scene.addLayer(workLayer);

  //scene.addLayer(new TextureLayer(scene, workLayer.mask.texture, fillerData.width, fillerData.height, fillerData.width, fillerData.height))

  scene.addLayer(new LineArtLayer(scene, resource.page, width, height));

  scene.addLayer(
    new BorderLayer(
      scene,
      0,
      0,
      fillerData.width,
      fillerData.height,
      0xff222222,
    ),
  );

  // let mask = new Mask(gl, fillerData)
  // resource.config[0].areas.forEach(area => mask.addArea(area))
  // mask.flush()

  //scene.addTestLayer(new TextureLayer(scene, mask.texture, fillerData.width, fillerData.height, width, height, ImageShaders.CommonGaussianBlurCut))
  //scene.addTestLayer(new TextureLayer(scene, mask.texture, fillerData.width, fillerData.height, width, height, ))

  //scene.addLayer(new TextureLayer(scene, hintLayer.mask.texture, fillerData.width, fillerData.height, width, height, ImageShaders.CommonGaussianBlur  ))
  //scene.addLayer(new DebugLayer(scene))

  //scene.addLayer(new ImageLayer(scene, resource.page, width, height, gl.LINEAR, ImageShaders.CommonGaussianBlur))
  //scene.addLayer(new TextureLayer(scene, fillerData.mapTexure, width, height, width, height))

  createButtons(fillerData);
  cssAdjustProgress(fillerData.data.coloredPercent);

  workLayer.initTask();

  if (fillerData.data.coloredPercent >= 100) {
    cssOnFinish(scene, workLayer, hintLayer, null);
  } else {
    // 创建手指提示，全图未完成时启动引导
    fingerHint = new FingerHint(scene, fillerData, fingerUrl);
    fingerHint.start();
  }
}

async function loadResource(): Promise<FillerResource> {
  const config = JSON.parse(configRaw) as AreaGroups;
  const [page, map, special, numberImage] = await Promise.all([
    loadImage(pageUrl),
    loadImage(mapUrl),
    loadImage(specialUrl),
    loadImage(numberFontUrl),
  ]);

  return new FillerResource(
    config,
    page as HTMLImageElement,
    map as HTMLImageElement,
    numberImage as HTMLImageElement,
    [],
    special as HTMLImageElement,
  );
}

function createButtons(fillerData: FillerData) {
  let data = fillerData.data.areaGroups;
  let htmlUndoned = [];
  let htmlDone = [];
  let html = [];
  let areaGroup: AreaGroup;
  let color: Color;
  for (var i = 0; i < data.length; i++) {
    areaGroup = data[i];
    color = new Color(areaGroup.color);
    if (areaGroup.isAllColored) {
      htmlDone.push(
        `<div id="color-btn-container-${i}" class="color-btn-container" onclick="selectColor(this, event, ${i})">`,
      );
      htmlDone.push(
        `<svg id="color-btn-progress-ring-${i}" class="color-btn-progress-ring" viewBox="0 0 48 48"><circle class="color-btn-progress-ring-track" cx="50%" cy="50%" r="45%" fill="transparent" stroke="#fff" stroke-width="5%" /> <circle id="color-btn-progress-ring-value-${i}" class="color-btn-progress-ring-value" cx="50%" cy="50%" r="45%" fill="transparent" stroke="#2ecc71" stroke-width="5%" stroke-linecap="round" /></svg>`,
      );
      htmlDone.push(
        `<div id="color-btn-${i}" class="color-btn" style="background-color:${color.css()}; color: ${color.gray < 192 ? "white" : "black"}">`,
      );
      htmlDone.push(`✓`);
      htmlDone.push(`</div>`);
      htmlDone.push(`</div>`);
    } else {
      if (
        areaGroup === fillerData.currentGroup ||
        areaGroup.progressPercent > 0.0
      ) {
      } // 需要展示circle progress
      htmlUndoned.push(
        `<div id="color-btn-container-${i}" class="color-btn-container" onclick="selectColor(this, event, ${i})">`,
      );
      htmlUndoned.push(
        `<svg id="color-btn-progress-ring-${i}" class="color-btn-progress-ring" viewBox="0 0 48 48"><circle class="color-btn-progress-ring-track" cx="50%" cy="50%" r="45%" fill="transparent" stroke="#fff" stroke-width="5%" /> <circle id="color-btn-progress-ring-value-${i}" class="color-btn-progress-ring-value" cx="50%" cy="50%" r="45%" fill="transparent" stroke="#2ecc71" stroke-width="5%" stroke-linecap="round" /></svg>`,
      );
      htmlUndoned.push(
        `<div id="color-btn-${i}" class="color-btn" style="background-color:${color.css()}; color: ${color.gray < 192 ? "white" : "black"}">`,
      );
      htmlUndoned.push(`${i + 1}`);
      htmlUndoned.push(`</div>`);
      htmlUndoned.push(`</div>`);
    }
  }
  html = htmlUndoned.concat(htmlDone);
  let c = document.querySelector("#color-btns");
  if (c != null) {
    c.innerHTML = html.join("");
  }

  // 选中当前color
  cssSelectColor(fillerData.currentGroupIndex);

  // 调整每个color item的进度
  for (var i = 0; i < data.length; i++) {
    let areaGroup = data[i];
    let percent = areaGroup.progressPercent;
    cssInitColorProgress(i, percent);
  }

  (window as any).selectColor = function (
    el: HTMLElement,
    event: MouseEvent,
    i: number,
  ) {
    console.log("select", el, event, i);
    fillerData.setCurrentGroup(i);
    document.querySelectorAll(".color-btn-container").forEach((item) => {
      item.classList.remove("color-btn-container-selected");
    });
    el.classList.add("color-btn-container-selected");
  };
}

/**
 * 调整整体完成进度条
 */
function cssAdjustProgress(percent: number) {
  let progressElem = document.getElementById("progress") as HTMLDivElement;
  let percentElem = document.getElementById("percent") as HTMLDivElement;

  percentElem.innerText = `${percent}%`;

  progressElem.style.width = `${percent}%`;
}

// 选中某个color, 自动切换到下一个颜色的时候触发调用
function cssSelectColor(i: number) {
  document.querySelectorAll(".color-btn-container").forEach((item) => {
    item.classList.remove("color-btn-container-selected");
  });
  let elem = document.getElementById(`color-btn-container-${i}`);
  elem?.classList.add("color-btn-container-selected");
}

// 设置color button的进度，即areagroup的进度
function cssSetColorProgress(i: number, percent: number) {
  const container = document.getElementById(`color-btn-container-${i}`)!;
  const progressCircle = document.getElementById(
    `color-btn-progress-ring-value-${i}`,
  )!;

  const containerWidth = container.clientWidth;
  const radius = containerWidth * 0.45;
  const circumference = 2 * Math.PI * radius;
  const offset = circumference - (percent * circumference) / 100;
  progressCircle.style.strokeDashoffset = offset.toString();

  if (percent >= 100) {
    // 如果此color已经完成，文本变为✓, 同时移动到队列后面
    const item = document.getElementById(`color-btn-${i}`)!;
    item.innerText = "✓";
  }
}

// 初始化color button进度
function cssInitColorProgress(i: number, percent: number) {
  const container = document.getElementById(`color-btn-container-${i}`)!;
  const progressCircle = document.getElementById(
    `color-btn-progress-ring-value-${i}`,
  )!;

  // 通过容器尺寸计算 SVG 半径
  const containerWidth = container.clientWidth;
  const radius = containerWidth * 0.45; // 对应 r="45%"

  // 计算周长并设置属性
  const circumference = 2 * Math.PI * radius;
  const offset = circumference - (percent * circumference) / 100;
  progressCircle.style.strokeDasharray = `${circumference} ${circumference}`;
  progressCircle.style.strokeDashoffset = offset.toString();
}

// 调整滚动条
function cssAdjustScroll(fd: FillerData) {
  let wrapper = document.getElementById("color-btns")!;
  let count =
    document.body.clientWidth /
    (wrapper.scrollWidth / fd.data.areaGroups.length); // 视窗内显示了多少个元素
  let width = document.body.clientWidth / count; // 每个元素占用的宽度
  // 计算位置
  let scrollpos =
    (wrapper.scrollWidth / fd.data.areaGroups.length) *
      (fd.currentGroupIndex - fd.doneBeforeCount) -
    (count * width) / 2 +
    width / 2;
  scrollpos = scrollpos < 0 ? 0 : scrollpos;
  // wrapper.scrollLeft = scrollpos ; // 不要直接设置scrollLeft，太突然没效果
  try {
    wrapper.scroll({ left: scrollpos, top: 0, behavior: "smooth" }); // 发现有些低端机不支持
  } catch (e) {
    console.log(e);
    wrapper.scrollLeft = scrollpos;
  }
}

/**
 * 数字item爆破动画
 */
function cssExplosionAnimation(
  numElem: HTMLElement,
  color: string,
  onfinish: Function,
) {
  let aniCanvas = document.createElement("canvas");
  aniCanvas.className = "finish-ani-canvas";
  let coords = numElem.getBoundingClientRect();
  aniCanvas.style.left = `${coords.left - 50}px`;
  aniCanvas.style.top = `${coords.top - 50}px`;
  aniCanvas.style.width = `${coords.width + 100}px`;
  aniCanvas.style.height = `${coords.height + 100}px`;
  document.body.append(aniCanvas);

  let explosion = new Explosion(aniCanvas, color, 50, () => {
    onfinish();
    aniCanvas.remove();
  });
  explosion.explode();
}

// 某个颜色填充完毕
function cssColorDone(fillerData: FillerData) {
  let i = fillerData.currentGroupIndex;
  let color = new Color(fillerData.currentGroup!.color).css();

  let wrapper = document.getElementById("color-btns")!;
  let buttonWrap = document.getElementById(`color-btn-container-${i}`)!;

  setTimeout(() => {
    //等环形进度条走完，开始爆破动画
    buttonWrap.style.visibility = "hidden";
    cssExplosionAnimation(buttonWrap, color, () => {
      // 爆破动画结束后，将元素移至末尾
      wrapper.lastElementChild!.after(buttonWrap);
      buttonWrap.style.visibility = "visible";
    });
  }, 300);
}

// 全部填完
function cssOnFinish(
  scene: FillerScene,
  workLayer: WorkLayer,
  hintLayer: HintLayer,
  audio: AudioPlayer | null,
) {
  // 立即将 canvas 底色改为透明，让 body 渐变色从绘图区域透出，避免 replay/消失动画中出现局部白色块
  scene.setClearTransparent();

  // 隐藏toolbar
  const toolbarBottom = document.getElementById(
    "toolbar-bottom",
  ) as HTMLDivElement;
  // 爆破动画结束后隐藏元素
  setTimeout(() => {
    if (scene.fillerData!.config.settings.sound) {
      audio?.playAudio(AudioType.AllDone);
    }
    scene.resetToResult();
    toolbarBottom.classList.add("hidden-toolbar-bottom"); // 添加 hidden 类，触发动画
    // 动画结束后隐藏元素
    setTimeout(() => {
      // toolbarBottom.style.display = 'none';
      scene.addLayer(
        new FrameLayer(
          scene,
          -4,
          -4,
          scene.fillerData!.width + 8,
          scene.fillerData!.height + 8,
          0xff9bceed,
          16,
        ),
      );
      hintLayer.enabled = false; // replay 期间隐藏 hint 覆盖层
      scene.invalidate();
      workLayer.replay().then(() => showPromoScreen());
    }, 500); // 过渡动画持续 0.5 秒
  }, 300); // 粒子爆破动画持续 0.3 秒

  setTimeout(() => {
    confetti();
  }, 300);
}

function showPromoScreen() {
  const canvas = document.getElementById("canvas") as HTMLCanvasElement;
  const promoScreen = document.getElementById("promo-screen") as HTMLDivElement;
  const promoColoring = document.getElementById(
    "promo-coloring",
  ) as HTMLImageElement;
  const promoSlogon = document.getElementById(
    "promo-slogon",
  ) as HTMLImageElement;

  // 预设图片资源（已在 init 阶段预加载，此处保留赋值保证兼容性）
  promoColoring.src = coloringPagesUrl;
  promoSlogon.src = slogonUrl;

  // 1. 将画布缩小至消失
  canvas.classList.add("canvas-shrink-out");

  // 2. canvas 过渡完成后（~600ms）展示宣传界面 + logo 淡入
  setTimeout(() => {
    canvas.style.display = "none";
    promoScreen.classList.add("visible");
    // 双 rAF：确保浏览器渲染初始态后再触发 transition
    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        promoColoring.classList.add("animate-in");
        promoSlogon.classList.add("animate-in");
        // 宣传界面出现后强化 CTA 按钮
        ctaHighlight();
      });
    });
  }, 620);
}

function onHint(audio: AudioPlayer, scene: FillerScene) {
  if (scene.fillerData?.config.settings.sound) {
    audio.playAudio(AudioType.Hint);
  }
  scene.hint();
}

function goback() {
  if (document.referrer.includes(window.location.hostname)) {
    window.history.back();
  } else {
    window.location.href = "/"; // 无来源时跳首页
  }
}

function vibrate() {
  // 判断浏览器是否支持震动
  var supportVibrate = "vibrate" in navigator;
  console.log("supportVibrate: " + supportVibrate);
  if (supportVibrate) {
    navigator.vibrate(30);
  }
}

function showToast(message: string) {
  const toast = document.getElementById("toast");
  if (toast) {
    toast.textContent = message;
    toast.classList.remove("toast-hidden");
    setTimeout(() => toast.classList.add("toast-hidden"), 2500);
  }
}

// 撒花动画，使用js-confetti库
function confetti() {
  const jsConfetti = new JSConfetti();
  jsConfetti.addConfetti();
}

// 点击其他区域，隐藏action-sheet
function onDocumentClick(evt: Event) {
  let elem = evt.target as HTMLElement;
  let setting = document.getElementById("setting") as HTMLDivElement;
  if (setting == elem || setting.contains(elem)) {
    return;
  }
  let actionSheet = document.getElementById("action-sheet") as HTMLDivElement;
  if (actionSheet.style.bottom == "0px") {
    actionSheet.style.bottom = "-1000px";
  }
}

function onActionSheetClick(evt: Event) {
  evt.stopPropagation();
}
