import { ITEM_TYPES, RDD_CONFIG } from "../constants.js";
import { RdDItem } from "../item.js";
import { BASE_CORPS_A_CORPS } from "./base-items.js";
import { Grammar } from "../grammar.js";
import { RdDInitiative } from "../combat/initiative.mjs";
import { MappingCreatureArme } from "./mapping-creature-arme.mjs";
import { Misc } from "../misc.js";

const categorie_parade = {
  "sans-armes": "Sans arme",
  "armes-naturelles": "Armes naturelles",
  "hast": "Armes d'hast",
  "batons": "Bâtons",
  "boucliers": "Boucliers",
  "dagues": "Dagues",
  "epees-courtes": "Epées courtes",
  "epees-longues": "Epées longues",
  "epees-lourdes": "Epées lourdes",
  "haches": "Haches",
  "lances": "Lances",
  "masses": "Masses",
}
export const ATTAQUE_TYPE = {
  UNE_MAIN: '(1 main)',
  DEUX_MAINS: '(2 mains)',
  CORPS_A_CORPS: '(corps à corps)',
  COMPETENCE: 'competence',
  TIR: '(tir)',
  LANCER: '(lancer)'
}
export const ATTAQUE_TYPE_MELEE = [ATTAQUE_TYPE.UNE_MAIN, ATTAQUE_TYPE.DEUX_MAINS, ATTAQUE_TYPE.CORPS_A_CORPS]

export const CORPS_A_CORPS = 'Corps à corps'
export const PUGILAT = 'pugilat'
export const EMPOIGNADE = RDD_CONFIG.encaissement.empoignade

/* -------------------------------------------- */
export class RdDItemArme extends RdDItem {

  static get ITEM_TYPE() { return ITEM_TYPES.arme }

  static get defaultIcon() { return "systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_gnome.webp" }

  penetration() { return parseInt(this.system.penetration ?? 0) }

  isParade() { return this.system.resistance > 0 && this.system.categorie_parade }
  isBouclier() { return RdDItemArme.getCategorieParade(this).includes('bouclier') }


  getCompetenceAction(main) {
    switch (main) {
      case ATTAQUE_TYPE.UNE_MAIN: return this.competence1Mains()
      case ATTAQUE_TYPE.DEUX_MAINS: return this.competence2Mains()
      case ATTAQUE_TYPE.LANCER: return this.system.lancer
      case ATTAQUE_TYPE.TIR: return this.system.tir
      default: return this.system.competence
    }
  }
  /* -------------------------------------------- */
  static valeurMain(valeurs, main) {
    valeurs = valeurs?.toString() ?? ""
    const table = valeurs.includes("/") ? valeurs.split("/") : [valeurs, valeurs]
    return parseInt(main == ATTAQUE_TYPE.DEUX_MAINS ? table[1] : table[0])
  }

  static getMainAttaque(competence) {
    switch (competence.system.categorie) {
      case 'tir': return ATTAQUE_TYPE.TIR
      case 'lancer': return ATTAQUE_TYPE.LANCER
    }
    if (competence.name.includes('2 main')) {
      return ATTAQUE_TYPE.DEUX_MAINS
    }
    return ATTAQUE_TYPE.UNE_MAIN
  }

  static getArme(arme) {
    switch (arme ? arme.type : '') {
      case ITEM_TYPES.arme: return arme;
      case ITEM_TYPES.competencecreature:
        return MappingCreatureArme.armeCreature(arme);
    }
    return RdDItemArme.pugilat();
  }

  static getCompetenceArme(arme, maniement) {
    switch (arme.type) {
      case ITEM_TYPES.competencecreature:
        return arme.name
      case ITEM_TYPES.arme:
        switch (maniement) {
          case ATTAQUE_TYPE.COMPETENCE: return arme.system.competence
          case ATTAQUE_TYPE.UNE_MAIN: return arme.competence1Mains()
          case ATTAQUE_TYPE.DEUX_MAINS: return arme.competence2Mains()
          case ATTAQUE_TYPE.TIR: case 'tir': return arme.system.tir
          case ATTAQUE_TYPE.LANCER: case 'lancer': return arme.system.lancer
          case ATTAQUE_TYPE.CORPS_A_CORPS: return CORPS_A_CORPS
        }
    }
    return undefined
  }

  getTypeAttaques() {
    return [
      ...(this.system.unemain && this.system.competence && this.system.resistance > 0) ? [ATTAQUE_TYPE.UNE_MAIN] : [],
      ...(this.system.deuxmains && this.system.competence && this.system.resistance > 0) ? [ATTAQUE_TYPE.DEUX_MAINS] : [],
      ...(this.system.lancer && this.system.resistance > 0) ? [ATTAQUE_TYPE.LANCER] : [],
      ...(this.system.tir) ? [ATTAQUE_TYPE.TIR] : [],
    ]
  }

  static computeNiveauArmes(armes, competences) {
    for (const arme of armes) {
      arme.system.niveau = RdDItemArme.niveauCompetenceArme(arme, competences);
    }
  }

  static niveauCompetenceArme(arme, competences) {
    const compArme = competences.find(it => Grammar.equalsInsensitive(it.name, arme.system.competence))
    return compArme?.system.niveau ?? -8
  }

  /* -------------------------------------------- */
  static getNomCategorieParade(arme) {
    const categorie = arme?.system ? RdDItemArme.getCategorieParade(arme) : arme;
    return categorie_parade[categorie];
  }

  /* -------------------------------------------- */
  static needArmeResist(armeAttaque, armeParade) {
    if (!armeAttaque || !armeParade) {
      return false;
    }
    // Epées parant une arme de bois (cf. page 115 ), une résistance est nécessaire
    let attCategory = RdDItemArme.getCategorieParade(armeAttaque);
    let defCategory = RdDItemArme.getCategorieParade(armeParade);

    return attCategory.match(/epees-/) && defCategory.match(/(haches|lances)/);
  }

  /* -------------------------------------------- */
  static getCategorieParade(armeData) {
    if (![ITEM_TYPES.arme, ITEM_TYPES.competencecreature].includes(armeData.type)) {
      return ''
    }
    if (armeData.system.categorie_parade) {
      return armeData.system.categorie_parade
    }
    // pour compatibilité avec des personnages existants
    if (armeData.system.competence == undefined) {
      return ITEM_TYPES.competencecreature;
    }
    let compname = armeData.system.competence.toLowerCase();
    if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) {
      return ''
    }

    if (compname.match('hache')) return 'haches'
    if (compname.match('hast')) return 'hast'
    if (compname.match('lance')) return 'lances'
    if (compname.match('bouclier')) return 'boucliers'
    if (compname.match('masse')) return 'masses'
    if (compname.match('epée') || compname.match('épée')) {
      if (armeData.name.toLowerCase().match(/(gnome)/))
        return 'epees-courtes'
      if (armeData.name.toLowerCase().match(/((e|é)pée dragone|esparlongue|demi-dragonne)/))
        return 'epees-longues'
      return 'epees-lourdes'
    }
    if (compname.match('dague')) {
      return 'dagues'
    }
    return 'sans-armes'
  }

  static defenseArmeParade(armeAttaque, armeParade) {
    const defCategory = RdDItemArme.getCategorieParade(armeParade)
    switch (defCategory) {
      case 'boucliers':
          return 'norm'
      case '':
        return 'impossible'
    }
    if (RdDItemArme.$isFleau(armeAttaque)) {
      return 'impossible'
    }

    const attCategory = RdDItemArme.getCategorieParade(armeAttaque)
    switch (attCategory) {
      case 'sans-armes':
      case 'armes-naturelles':
        return defCategory == attCategory ? 'norm' : 'impossible'
      default:
        return RdDItemArme.needParadeSignificative(armeAttaque, armeParade) ? 'sign' : 'norm'
    }
  }

  static $isFleau(armeAttaque) {
    return armeAttaque?.system?.competence?.toLowerCase().match(/(fléau)/);
  }

  /* -------------------------------------------- */
  static needParadeSignificative(armeAttaque, armeParade) {
    if (!armeAttaque || !armeParade) {
      return false;
    }
    // categories d'armes à la parade (cf. page 115 )
    const attCategory = RdDItemArme.getCategorieParade(armeAttaque)
    const defCategory = RdDItemArme.getCategorieParade(armeParade)
    // bouclier et mêmes catégorie: peuvent se parer sans difficulté
    if (defCategory == 'boucliers') {
      return false;
    }
    // Parer avec une hache ou une arme d’hast exige toujours une significative
    if (defCategory.match(/(hast|haches)/)) {
      return true;
    }
    if (defCategory == attCategory) {
      return false;
    }
    // les épées se parent entre elles
    if (defCategory.match(/epees-/) && attCategory.match(/epees-/)) {
      return false;
    }
    // l'épée gnome pare la dague
    if (defCategory == 'epees-courtes' && attCategory == 'dagues') {
      return false;
    }
    // la dague pare les épées courtes et légères
    if (defCategory == 'dagues' && attCategory.match(/epees-(courtes|legeres)/)) {
      return false;
    }
    return true;
  }

  static dommagesReels(arme, maniement) {
    switch (maniement) {
      case 'tir':
      case 'lancer':
      case 'competence':
        return Number(arme.system.dommages)
    }
    if (arme.system.unemain && arme.system.deuxmains) {
      const containsSlash = !Number.isInteger(arme.system.dommages) && arme.system.dommages.includes("/")
      if (!containsSlash) {
        ui.notifications.info("Les dommages de l'arme à 1/2 mains " + arme.name + " ne sont pas corrects (ie sous la forme X/Y)");
        return Number(arme.system.dommages)
      }
      const tableauDegats = arme.system.dommages.split("/");
      return Number(tableauDegats[maniement == ATTAQUE_TYPE.UNE_MAIN ? 0 : 1])
    }
    return Number(arme.system.dommages);
  }

  /* -------------------------------------------- */
  static armeUneOuDeuxMains(arme, aUneMain) {
    if (arme && !arme.system.cac) {
      arme = foundry.utils.deepClone(arme);
      arme.system.dommagesReels = RdDItemArme.dommagesReels(arme, aUneMain ? ATTAQUE_TYPE.UNE_MAIN : ATTAQUE_TYPE.DEUX_MAINS)
    }
    return arme;
  }

  competence1Mains() {
    return this.system.competence.replace(" 2 mains", " 1 main");
  }

  competence2Mains() {
    return this.system.competence.replace(" 1 main", " 2 mains");
  }

  static isUtilisable(arme) {
    switch (arme.type) {
      case ITEM_TYPES.arme: return arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0)
      case ITEM_TYPES.competencecreature: return true
    }
    return false
  }

  isAttaque() {
    return this.system.resistance > 0 || (this.system.tir != '' && this.system.portee_courte > 0)
  }

  isEmpoignade() {
    return this.system.mortalite == RDD_CONFIG.encaissement.empoignade
  }

  isPossession() {
    return this.system.mortalite == RDD_CONFIG.encaissement.possession
  }

  isUtilisableEmpoigne() {
    return this.system.baseInit == 3 || this.system.baseInit == 4 || this.system.competence == "Dague"
  }

  static pugilat(actor) {
    return RdDItemArme.$corpsACorps(actor, 'Pugilat', PUGILAT)
  }

  static empoignade(actor) {
    return RdDItemArme.$corpsACorps(actor, 'Empoignade', RDD_CONFIG.encaissement.empoignade)
  }

  static $corpsACorps(actor, name, cac) {
    const competence = actor?.getCompetenceCorpsACorps() ?? BASE_CORPS_A_CORPS
    const melee = actor ? actor.system.carac['melee'].value : 0
    return new RdDItemArme({
      _id: Misc.fakeId(cac),
      name: name,
      type: ITEM_TYPES.arme,
      img: competence.img,
      system: {
        initiative: RdDInitiative.getRollInitiative(melee, competence.system.niveau),
        equipe: true,
        rapide: true,
        force: 0,
        dommages: "0",
        dommagesReels: 0,
        mortalite: cac == RDD_CONFIG.encaissement.empoignade ? RDD_CONFIG.encaissement.empoignade : RDD_CONFIG.encaissement.nonmortel,
        competence: CORPS_A_CORPS,
        resistance: 1,
        baseInit: cac == RDD_CONFIG.encaissement.empoignade ? 3 : 4,
        cac: cac,
        deuxmains: true,
        categorie_parade: 'sans-armes'
      }
    })
  }

}
