import { ITEM_TYPES } 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: it => 'fa-solid fa-sparkles',
  filter: it => game.user.isGM || DialogEnchanter.isEnchantable(it),
  optionsFilter: options => options.editable,
  action: (item, actor) => DialogEnchanter.enchanter(item)
}

export class DialogEnchanter extends Dialog {

  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: actor,
      item: item,
      reve: item.system.pr,
      sorts: sorts,
      nouveauxpr: 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 ${item.system.quantite > 1 ? '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 html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/enchantement/dialog-enchanter.hbs`, enchanter)
    const dialog = new DialogEnchanter(enchanter, html)
    dialog.render(true)
  }

  constructor(enchanter, html) {
    let options = { classes: ["dialog-enchanter"], width: 400, height: 'fit-content', 'z-index': 99999 }
    let conf = {
      title: `Enchanter une ${enchanter.type}`,
      content: html,
      default: "enchanter",
      buttons: {
        "enchanter": { label: "Enchanter", callback: it => this.onEnchanter() }
      }
    };
    super(conf, options)
    this.html = html
    this.enchanter = enchanter
    this.item = enchanter.item
  }

  activateListeners(html) {
    super.activateListeners(html)
    this.html = html
    this.html.find("input.enchantement").change(event => this.$onSelectEnchantement(event))
    this.html.find("input.reve").change(event => this.$onForceReve(event))
  }

  $onSelectEnchantement(event) {
    const addReve = $(event.currentTarget).data('reve')
    this.enchanter.idx = $(event.currentTarget).data('idx')
    this.enchanter.reve = this.item.system.pr + Number(addReve)
    this.html.find("input.reve").val(this.enchanter.reve)
    for (let idx = 0; idx < this.enchanter.nouveauxpr.length; idx++) {
      if (idx != this.enchanter.idx) {
        this.html.find(`.enchantement[data-idx='${idx}']`).prop("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() {
    foundry.utils.mergeObject(this.enchanter,
      {
        rendrepurifie: this.html.find("input.rendrepurifie").prop("checked"),
        rendrepermanent: this.html.find("input.rendrepermanent").prop("checked"),
        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))
        }
      }
    }
  }
}