import { ACTOR_TYPES, ITEM_TYPES, renderTemplate } from "../constants.js"
import { RdDItemSort } from "../item-sort.js"
import { Misc } from "../misc.js"

export const ACTION_ITEM_ENCHANTER = {
  code: "item-enchanter", label: "Enchanter", icon: () => "fa-solid fa-sparkles",
  filter: it => DialogEnchanter.isEnchantable(it) && it.parent?.type != ACTOR_TYPES.commerce,
  action: (item, actor) => DialogEnchanter.enchanter(item)
}

export class DialogEnchanter extends foundry.applications.api.DialogV2 {
  static isEnchantable(item) {
    if (!item.isEnchantementPossible) return false
    if (game.user.isGM) return true
    if (item.system.prpermanent) return false
    if (!item.parent?.isHautRevant()) return false
    return RdDItemSort.lancements(RdDItemSort.findEnchantement(item.parent)) > 0
      || RdDItemSort.lancements(RdDItemSort.findPurification(item.parent)) > 0
      || RdDItemSort.lancements(RdDItemSort.findPermanence(item.parent)) > 0
  }

  static dateEnchantement() {
    return game.system.rdd.calendrier.getTimestamp().debutJournee().indexDate
  }

  static async enchanter(item) {
    const actor = item.parent
    const sorts = {
      enchantement: RdDItemSort.findEnchantement(actor),
      purification: RdDItemSort.findPurification(actor),
      permanence: RdDItemSort.findPermanence(actor)
    }
    const nouveauxpr = (sorts.enchantement?.system.lancements ?? []).map(it => it.reve)
    const purification = (sorts.purification?.system.lancements ?? []).find(it => true)
    const permanence = (sorts.permanence?.system.lancements ?? []).find(it => true)
    const enchanter = {
      type: item.type == ITEM_TYPES.potion ? "potion" : Misc.typeName("Item", item.type),
      actor, item,
      reve: item.system.pr,
      sorts, nouveauxpr,
      purification: purification != undefined,
      permanence: permanence != undefined,
      options: { isGM: game.user.isGM }
    }
    if (!item.isEnchantementPossible) {
      ui.notifications.info("Seuls les liquides et les gemmes sont enchantables")
      return
    }
    if (item.system.prpermanent) {
      ui.notifications.info(`La ${enchanter.type} est permanente`)
      return
    }
    if (!game.user.isGM) {
      if (!(actor?.isPersonnage() || actor?.isHautRevant())) {
        ui.notifications.info(`Seul un haut rêvant peut enchanter une ${enchanter.type}`)
        return
      }
      if (item.system.quantite != 1) {
        ui.notifications.info(`Impossible d'enchanter ${item.system.quantite} ${enchanter.type}s en une seule fois`)
        return
      }
      if (!(nouveauxpr.length > 0 || purification || permanence)) {
        ui.notifications.info("Le haut-rêvant n'a lancé de rituel d'enchantement")
        return
      }
      if (item.system.magique && item.system.purifie && !purification && !permanence) {
        ui.notifications.info(`La ${enchanter.type} est déjà enchantée et doit être purifiée`)
        return
      }
    }
    const content = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/enchantement/dialog-enchanter.hbs", enchanter)
    new DialogEnchanter(enchanter, content).render({ force: true })
  }

  constructor(enchanter, content) {
    super({
      title: `Enchanter une ${enchanter.type}`,
      content,
      classes: ["dialog-enchanter"],
      position: { width: 400, height: 'fit-content' },
      buttons: [
        { label: "Enchanter", action: "enchanter", callback: () => this.onEnchanter() }
      ]
    })
    this.enchanter = enchanter
    this.item = enchanter.item
  }

  _onRender(context) {
    super._onRender(context)
    this.element.querySelectorAll("input.enchantement").forEach(el =>
      el.addEventListener("change", event => this.$onSelectEnchantement(event))
    )
    this.element.querySelectorAll("input.reve").forEach(el =>
      el.addEventListener("change", event => this.$onForceReve(event))
    )
  }

  $onSelectEnchantement(event) {
    const target = event.currentTarget
    const addReve = target.dataset.reve
    this.enchanter.idx = target.dataset.idx
    this.enchanter.reve = this.item.system.pr + Number(addReve)
    const revealue = this.element.querySelector("input.reve")
    if (revealue) revealue.value = this.enchanter.reve
    for (let idx = 0; idx < this.enchanter.nouveauxpr.length; idx++) {
      if (idx != this.enchanter.idx) {
        const other = this.element.querySelector(`.enchantement[data-idx='${idx}']`)
        if (other) other.checked = false
      }
    }
  }

  $onForceReve(event) {
    const newReve = Number(event.currentTarget.value)
    if (this.enchanter.reve != newReve) {
      this.enchanter.idx = undefined
    }
    this.enchanter.reve = newReve
  }

  async onEnchanter() {
    const el = this.element
    foundry.utils.mergeObject(this.enchanter, {
      rendrepurifie: el.querySelector("input.rendrepurifie")?.checked ?? false,
      rendrepermanent: el.querySelector("input.rendrepermanent")?.checked ?? false,
      addreve: this.enchanter.reve != this.item.system.pr
    }, { inplace: true })
    const item = this.enchanter.item
    const actor = this.enchanter.actor
    if (this.enchanter.reve == 0) {
      await item.update({
        "system.pr": 0, "system.magique": false, "system.purifie": false,
        "system.prpermanent": false, "system.prdate": 0
      })
    }
    else {
      const isPurifiee = this.enchanter.addreve
        ? (this.enchanter.rendrepurifie && (item.item.system.pr == 0 ? true : item.system.purifie))
        : (this.enchanter.rendrepurifie || item.system.purifie)
      await item.update({
        "system.pr": this.enchanter.reve,
        "system.magique": true,
        "system.purifie": isPurifiee,
        "system.prpermanent": item.system.prpermanent || this.enchanter.rendrepermanent,
        "system.prdate": DialogEnchanter.dateEnchantement()
      })
      if (actor) {
        if (this.enchanter.rendrepurifie) {
          await RdDItemSort.changeLancementsSort(this.enchanter.sorts.purification, it => it.slice(1))
        }
        if (this.enchanter.rendrepermanent) {
          await RdDItemSort.changeLancementsSort(this.enchanter.sorts.permanence, it => it.slice(1))
        }
        if (this.enchanter.addreve && this.enchanter.idx != undefined) {
          await RdDItemSort.changeLancementsSort(RdDItemSort.findEnchantement(actor), it => it.toSpliced(this.enchanter.idx, 1))
        }
      }
    }
  }
}
