import { ITEM_TYPES } from "../constants.js"
import { ROLL_TYPE_SORT } from "./roll-constants.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_COMP } from "./roll-part-comp.mjs"
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
import { TMRUtility } from "../tmr-utility.js"
import { RdDItemSort } from "../item-sort.js"
import { RollPartSelect } from "./roll-part-select.mjs"
import { CARACS } from "../rdd-carac.js"

export const PART_SORT = "sort"

export class RollPartSort extends RollPartSelect {

  onReady(rollParts) {
    // TODO: utiliser un hook pour écouter les déplacements dans les TMRs?
  }

  get code() { return PART_SORT }
  get section() { return ROLLDIALOG_SECTION.CHOIX }

  prepareContext(rollData) {
    const current = this.getCurrent(rollData)
    current.sortDiffOptions = Array.from(
      { length: 20 },
      (_, i) => ({ value: -20 + i, label: String(-20 + i) })
    )
  }

  get rollTypes() { return [ROLL_TYPE_SORT] }
  isValid(rollData) { return rollData.active.actor.isPersonnage() && rollData.active.actor.isHautRevant() }
  visible(rollData) { return RollPart.isRollType(rollData, ROLL_TYPE_SORT) }

  restore(rollData) {
    const saved = this.getSaved(rollData)
    this.setCurrent(rollData, {
      key: saved.key,
      isReserve: saved.isReserve,
      ptreve: saved.ptreve,
      value: saved.value,
    })
  }

  store(rollData, targetData) {
    const current = this.getCurrent(rollData)
    this.setSaved(targetData, {
      key: current.key,
      isReserve: current.isReserve,
      ptreve: current.ptreve,
      value: current.value,
    })
  }

  loadRefs(rollData) {
    const refs = this.getRefs(rollData)
    const coord = this.getCoord(rollData)
    const draconics = rollData.active.actor.getDraconics()
    const sorts = rollData.active.actor.itemTypes[ITEM_TYPES.sort]
      .map(s => RollPartSort.$extractSort(s, coord, draconics, rollData.active.actor))

    foundry.utils.mergeObject(refs,
      {
        coord: coord,
        tmr: TMRUtility.getTMR(coord),
        reve: this.getReveActuel(rollData),
        draconics: draconics,
        all: sorts,
        sorts: sorts.filter(it => RdDItemSort.isSortOnCoord(it.sort, coord))
      },
      { inplace: true }
    )
    if (refs.sorts.length > 0) {
      this.$selectSort(rollData, this.getSaved(rollData))
    }
  }

  getReveActuel(rollData) {
    return rollData.active.actor.system.reve.reve.value
  }

  getCoord(rollData) {
    return rollData.active.actor.system.reve.tmrpos.coord
  }

  choices(refs) { return refs.sorts }

  static $extractSort(sort, coord, draconics, actor) {
    const isDiffVariable = RdDItemSort.isDifficulteVariable(sort)
    const isReveVariable = RdDItemSort.isCoutVariable(sort)
    return {
      key: sort.id,
      label: sort.name,
      value: isDiffVariable ? -7 : parseInt(sort.system.difficulte),
      ptreve: isReveVariable ? 1 : sort.system.ptreve,
      caseTMR: RdDItemSort.getCaseTMR(sort),
      bonusCase: RdDItemSort.getCaseBonus(sort, coord, actor),
      isDiffVariable: isDiffVariable,
      isReveVariable: isReveVariable,
      isReserve: false,
      sort: sort,
      draconics: RdDItemSort.getDraconicsSort(draconics, sort).map(it => it.name),
    }
  }

  getAjustements(rollData) {
    const current = this.getCurrent(rollData)
    if (current) {
      const sort = { label: current.label, value: current.value }
      const reserve = current.isReserve ? [{ label: `Mise en réserve en ${this.getCoord(rollData)}` }] : []
      const bonusCase = current.bonusCase ? [{ label: `Bonus case +${current.bonusCase}%` }] : []
      const reve = { label: `Dépense de rêve ${current.ptreve}` }
      return [sort, ...bonusCase, reve, ...reserve]
    }
    return []
  }

  $selectSort(rollData, values) {
    const current = this.selectByKey(rollData, values.key)
    if (values.ptreve != undefined) {
      current.ptreve = values.ptreve
    }
    if (current.isDiffVariable && values.value != undefined) {
      current.value = values.value
    }
    if (values.isReserve != undefined) {
      current.isReserve = values.isReserve
    }
  }

  async _onRender(rollDialog, context, options) {
    const current = this.getCurrent(rollDialog.rollData)
    const selectSort = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-sort"]`)
    const inputDiff = rollDialog.element.querySelector(`roll-section[name="${this.code}"] [name="diff-var"]`)
    const inputPtReve = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="ptreve-var"]`)
    const checkboxReserve = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="reserve"]`)

    selectSort.addEventListener("change", e => {
      const selectOptions = e.currentTarget.options
      const index = selectOptions.selectedIndex
      this.$selectSort(rollDialog.rollData, { key: selectOptions[index]?.value })
      rollDialog.render()
    })

    inputDiff?.addEventListener("change", e => {
      current.value = parseInt(e.currentTarget.value)
      rollDialog.render()
    })
    inputPtReve?.addEventListener("change", e => {
      current.ptreve = parseInt(e.currentTarget.value)
      rollDialog.render()
    })
    checkboxReserve?.addEventListener("change", e => {
      current.isReserve = e.currentTarget.checked
      rollDialog.render()
    })
  }

  impactOtherPart(part, rollData) {
    if (this.visible(rollData)) {
      const current = this.getCurrent(rollData)
      switch (part.code) {
        case PART_CARAC: return part.filterCaracs(rollData, [CARACS.REVE])
        case PART_COMP: return part.filterComps(rollData, current.draconics ?? [])
      }
    }
    return undefined
  }

}
