import "../xregexp-all.js";
import { RdDCarac } from "../../rdd-carac.js";
import { RdDItemCompetence } from "../../item-competence.js";
import { RdDUtility } from "../../rdd-utility.js";
import { TextRollManager } from "./text-roll-formatter.js";

const REGECP_CARAC = "(?<carac>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)"
const REGEXP_COMP = "(\\/(?<competence>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+))?"
const REGEXP_DIFF = "(/(?<diff>[\\+\\-]?\\d+(d\\d+)?))?"
const REGEXP_ROLL_CARAC_COMP = REGECP_CARAC + REGEXP_COMP + REGEXP_DIFF
const XREGEXP_ROLL_CARAC_COMP = XRegExp("@roll\\[" + REGEXP_ROLL_CARAC_COMP + "\\]", 'giu')

/**
 * classe pour gérer les jets de caractéristique/compétence depuis
 * les journaux/descriptions
 */
export class TextRollCaracCompetence {
  get code() { return 'carac' }
  get template() { return `systems/foundryvtt-reve-de-dragon/templates/apps/textroll/link-text-roll-carac-competence.hbs` }

  async onReplaceRoll(context) {
    const handler = new CaracCompetenceTextBuilder(context)
    return await handler.replaceAll()
  }

  async onRollText(event, actor) {
    const node = TextRollManager.getNode(event)
    const caracCode = node.data('carac-code')
    if (caracCode) {
      const competence = node.data('competence')
      const diff = await this.calculDiff(node)
      const actors = this.getSelectedActors(actor)
      actors.forEach(async it => await this.doRoll(it, caracCode, competence, diff))
    }
  }

  async calculDiff(node) {
    const diff = node.data('diff') ?? 0
    if (!Number.isInteger(diff)) {
      const roll = new Roll(diff)
      await roll.evaluate()
      await roll.toMessage({ flavor: `La difficulté de ${diff} a donné ${roll.total}` })
      return roll.total
    }
    return diff
  }

  async doRoll(actor, caracCode, competence, diff) {
    caracCode = actor.mapCarac(caracCode)
    if (caracCode) {
      if (competence) {
        await actor.rollCaracCompetence(caracCode, competence, diff)
      }
      else {
        await actor.rollCarac(caracCode, { diff })
      }
    }
  }

  getSelectedActors(actor) {
    const selected = canvas.tokens.controlled.map(it => it.actor).filter(it => it)
    if (selected.length > 0) {
      return selected
    }
    actor = actor ?? RdDUtility.getSelectedActor()
    if (actor) {
      return [actor]
    }
    return []
  }
}

class CaracCompetenceTextBuilder {
  constructor(context) {
    this.context = context
  }

  async replaceAll() {
    await XRegExp.forEach(this.context.text, XREGEXP_ROLL_CARAC_COMP, async (rollMatch, i) => await this.replaceMatch(rollMatch, i))
    return this.context.text
  }

  async replaceMatch(rollMatch, i) {
    const carac = RdDCarac.caracDetails(rollMatch.carac)
    if (carac) {
      const competence = rollMatch.competence ? RdDItemCompetence.findCompetence(this.context.competences, rollMatch.competence) : undefined
      const replacement = await TextRollManager.createRollText(this.context,
        {
          code: this.context.code,
          carac: carac,
          competence: competence?.name,
          diff: rollMatch.diff,
        })
      this.context.text = this.context.text.replace(rollMatch[0], replacement)
    }
  }
}