import { TokenActor } from "../technical/actor-token.mjs"
import { StatusEffects } from "../settings/status-effects.js"
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
import { PART_DEFENSE } from "./roll-part-defense.mjs"


export class RollBasicParts {

  static restore(rollData) {
    rollData.ids.sceneId = rollData.ids.sceneId ?? canvas?.scene?.id
    rollData.active = RollBasicParts.getTokenActor(rollData)
    rollData.opponent = RollBasicParts.getTokenActorOpponent(rollData)
    if (rollData.type && rollData.type.opposed == undefined) {
      rollData.type.opposed = rollData.opponent != null
    }
  }

  static loadSurprises(rollData, type = rollData.type.current) {
    if (!rollData.type.passif) {
      RollBasicParts.loadSurprise(rollData.active, RollBasicParts.getForceRequiseActiveActor(rollData, type))
      RollBasicParts.loadSurprise(rollData.opponent, 0)
    }
  }

  static loadSurprise(who, forceRequise) {
    if (who?.actor) {
      foundry.utils.mergeObject(who,
        StatusEffects.getActorEffetSurprise(who.actor),
        { overwrite: true, inPlace: true })
    }
  }

  static getForceRequiseActiveActor(rollData, type) {
    switch (type) {
      case ROLL_TYPE_ATTAQUE: return rollData.current[PART_ATTAQUE].forceRequise
      case ROLL_TYPE_DEFENSE: return rollData.current[PART_DEFENSE].forceRequise
      default: return 0
    }
  }

  static initFrom(rollData) {
    const isOpposed = rollData.type.opposed && rollData.opponent
    return {
      selected: {},
      type: rollData.type,
      ids: {
        sceneId: rollData.ids.sceneId,
        actorId: rollData.ids.actorId,
        actorTokenId: rollData.ids.actorTokenId,
        opponentId: isOpposed ? rollData.ids.opponentId : undefined,
        opponentTokenId: isOpposed ? rollData.ids.opponentTokenId : undefined,
      }
    }
  }

  static prepareDefense(attackerRoll) {
    if (!attackerRoll.passeArme) {
      attackerRoll.passeArme = foundry.utils.randomID(16);
    }
    return {
      ids: RollBasicParts.reverseIds(attackerRoll),
      active: attackerRoll.opponent,
      opponent: attackerRoll.active,
      attackerRoll: attackerRoll,
      passeArme: attackerRoll.passeArme,
      show: { encaissement: true }
    }
  }

  static reverseIds(rollData) {
    return {
      sceneId: rollData.ids.sceneId,
      actorId: rollData.ids.opponentId,
      actorTokenId: rollData.ids.opponentTokenId,
      opponentId: rollData.ids.actorId,
      opponentTokenId: rollData.ids.actorTokenId
    }
  }

  static getTokenActor(rollData) {
    if (rollData.ids.actorTokenId) {
      return TokenActor.fromTokenId(rollData.ids.actorTokenId, rollData.ids.sceneId)
    }
    else {
      const controlled = canvas?.tokens?.controlled
      const actorId = rollData.ids.actorId ?? (controlled?.length == 1
        ? controlled[0]?.actor?.id
        : undefined)
      return TokenActor.fromActorId(actorId, () => { throw new Error("Pas d'acteur sélectionné") })
    }
  }

  static getTokenActorOpponent(rollData) {
    if (rollData.ids.opponentTokenId) {
      return TokenActor.fromTokenId(rollData.ids.opponentTokenId, rollData.ids.sceneId)
    }
    else if (rollData.ids.opponentId) {
      return TokenActor.fromActorId(rollData.ids.opponentId)
    }
    else {
      const targets = Array.from(game.user.targets)
      if (targets.length == 1) {
        return TokenActor.fromToken(targets[0])
      }
      else {
        return undefined
      }
    }
  }
}
