/**
 * Chroniques de l'Étrange — Système FoundryVTT
 *
 * Chroniques de l'Étrange est un jeu de rôle édité par Antre-Monde Éditions.
 * Ce système FoundryVTT est une implémentation indépendante et n'est pas
 * affilié à Antre-Monde Éditions,
 * mais a été réalisé avec l'autorisation d'Antre-Monde Éditions.
 *
 * @author    LeRatierBretonnien
 * @copyright 2024–2026 LeRatierBretonnien
 * @license   CC BY-NC-SA 4.0 – https://creativecommons.org/licenses/by-nc-sa/4.0/
 */

import { getLoksyuData, setLoksyuData } from "./singletons.js"
import { SYSTEM_ID } from "../../config/constants.js"

export class CDELoksyuApp extends foundry.applications.api.HandlebarsApplicationMixin(
  foundry.applications.api.ApplicationV2
) {
  static DEFAULT_OPTIONS = {
    id: "cde-loksyu-app",
    tag: "div",
    window: {
      title: "CDE.Loksyu",
      icon: "fas fa-yin-yang",
      resizable: false,
    },
    classes: ["cde-app", "cde-loksyu-standalone"],
    position: { width: 520, height: "auto" },
    actions: {
      resetElement: CDELoksyuApp.#onResetElement,
      resetAll:     CDELoksyuApp.#onResetAll,
      zoomVisual:   CDELoksyuApp.#onZoomVisual,
    },
  }

  static PARTS = {
    main: {
      template: `systems/${SYSTEM_ID}/templates/apps/cde-loksyu-app.html`,
    },
  }

  /** @type {Function|null} bound hook handler */
  _updateHook = null

  /** @type {Function|null} updateSetting hook handler (for socket-propagated writes) */
  _settingHook = null

  /** Singleton accessor — open or bring to front */
  static open() {
    const existing = Array.from(foundry.applications.instances.values()).find(
      (app) => app instanceof CDELoksyuApp
    )
    if (existing) { existing.bringToFront(); return existing }
    const app = new CDELoksyuApp()
    app.render(true)
    return app
  }

  async _prepareContext() {
    const sys = getLoksyuData()
    const ELEMENTS = [
      { key: "wood",  nameKey: "CDE.Wood",  qualKey: "CDE.WoodQualities",  img: `systems/${SYSTEM_ID}/images/cde_bois.webp` },
      { key: "fire",  nameKey: "CDE.Fire",  qualKey: "CDE.FireQualities",  img: `systems/${SYSTEM_ID}/images/cde_feu.webp` },
      { key: "earth", nameKey: "CDE.Earth", qualKey: "CDE.EarthQualities", img: `systems/${SYSTEM_ID}/images/cde_terre.webp` },
      { key: "metal", nameKey: "CDE.Metal", qualKey: "CDE.MetalQualities", img: `systems/${SYSTEM_ID}/images/cde_metal.webp` },
      { key: "water", nameKey: "CDE.Water", qualKey: "CDE.WaterQualities", img: `systems/${SYSTEM_ID}/images/cde_eau.webp` },
    ]

    return {
      canEdit: game.user.isGM,
      elements: ELEMENTS.map((el) => ({
        ...el,
        yang: sys[el.key]?.yang ?? 0,
        yin:  sys[el.key]?.yin  ?? 0,
      })),
    }
  }

  _onRender(context, options) {
    super._onRender(context, options)
    this.#bindInputs()

    if (!this._updateHook) {
      this._updateHook = Hooks.on("cde:loksyuUpdated", () => this.render())
    }
    if (!this._settingHook) {
      this._settingHook = Hooks.on("updateSetting", (setting) => {
        if (setting.key === `${SYSTEM_ID}.loksyuData`) this.render()
      })
    }
  }

  _onClose(options) {
    if (this._updateHook !== null) {
      Hooks.off("cde:loksyuUpdated", this._updateHook)
      this._updateHook = null
    }
    if (this._settingHook !== null) {
      Hooks.off("updateSetting", this._settingHook)
      this._settingHook = null
    }
    super._onClose(options)
  }

  #bindInputs() {
    const inputs = this.element?.querySelectorAll("input[data-field]")
    if (!inputs?.length) return
    inputs.forEach((input) => {
      input.addEventListener("change", async (ev) => {
        const field = ev.currentTarget.dataset.field
        const val   = parseInt(ev.currentTarget.value, 10)
        if (!field || isNaN(val)) return
        // field is like "wood.yin" or "fire.yang"
        const [aspect, dim] = field.split(".")
        if (!aspect || !dim) return
        const data = getLoksyuData()
        if (!data[aspect]) data[aspect] = { yin: 0, yang: 0 }
        data[aspect][dim] = Math.max(0, val)
        await setLoksyuData(data)
      })
    })
  }

  static async #onResetElement(event, target) {
    const key = target.dataset.element
    if (!key) return
    const data = getLoksyuData()
    data[key] = { yin: 0, yang: 0 }
    await setLoksyuData(data)
  }

  static async #onResetAll(_event, _target) {
    const KEYS = ["wood", "fire", "earth", "metal", "water"]
    const data = getLoksyuData()
    for (const k of KEYS) data[k] = { yin: 0, yang: 0 }
    await setLoksyuData(data)
  }

  static #onZoomVisual(_event, target) {
    new ImagePopout(target.src, {
      title: game.i18n.localize("CDE.LoksyuDiagramTitle"),
      shareable: false,
    }).render(true)
  }
}
