import { Grammar } from "./grammar.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"
import { ITEM_TYPES } from "./constants.js";
import { BASE_CORPS_A_CORPS } from "./item/base-items.js";
import { RdDCombatManager } from "./rdd-combat.js";

const nomCategorieParade = {
  "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",
}

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

  static isArme(item) {
    return item.type == ITEM_TYPES.arme || RdDItemCompetenceCreature.getCategorieAttaque(item);
  }

  /* -------------------------------------------- */
  static getArme(arme) {
    switch (arme ? arme.type : '') {
      case ITEM_TYPES.arme: return arme;
      case ITEM_TYPES.competencecreature:
        return RdDItemCompetenceCreature.armeCreature(arme);
    }
    return RdDItemArme.corpsACorps();
  }

  static getCompetenceArme(arme, maniement) {
    switch (arme.type) {
      case ITEM_TYPES.competencecreature:
        return arme.name
      case ITEM_TYPES.arme:
        switch (maniement) {
          case 'competence': return arme.system.competence;
          case 'unemain': return RdDItemArme.competence1Mains(arme);
          case 'deuxmains': return RdDItemArme.competence2Mains(arme);
          case 'tir': return arme.system.tir;
          case 'lancer': return arme.system.lancer;
        }
    }
    return undefined
  }

  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 nomCategorieParade[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 (armeData.system.categorie_parade) {
      return armeData.system.categorie_parade
    }
    // pour compatibilité avec des personnages existants
    if (armeData.type == ITEM_TYPES.competencecreature || armeData.system.categorie == 'creature') {
      return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : '')
    }
    if (!armeData.type.match(/arme|competencecreature/)) {
      return ''
    }
    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)
    if (defCategory == 'bouclier') {
      return 'norm'
    }
    if (armeAttaque.system.competence.toLowerCase().match(/(fléau)/)) {
      return ''
    }
    if (armeParade.system.tir) {
      return ''
    }
    const attCategory = RdDItemArme.getCategorieParade(armeAttaque)
    switch (attCategory) {
      case 'armes-naturelles': case 'sans-armes':
        return defCategory == 'sans-armes' ? 'norm' : ''
      default:
        return RdDItemArme.needParadeSignificative(armeAttaque, armeParade) ? 'sign' : 'norm'
    }
  }

  /* -------------------------------------------- */
  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 == 'unemain' ? 0 : 1])
    }
    return Number(arme.system.dommages);
  }

  /* -------------------------------------------- */
  static armeUneOuDeuxMains(arme, aUneMain) {
    if (arme && !arme.system.cac) {
      arme = foundry.utils.duplicate(arme);
      arme.system.dommagesReels = RdDItemArme.dommagesReels(arme, aUneMain ? 'unemain' : 'deuxmains')
    }
    return arme;
  }

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

  static competence2Mains(arme) {
    return arme.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
  }

  static isAttaque(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 arme.system.iscombat && RdDItemCompetenceCreature.isAttaque(item)
    }
    return false
  }

  static isParade(arme) {
    switch (arme.type) {
      case ITEM_TYPES.arme:
        return arme.system.equipe && arme.system.resistance > 0 && true/* TODO: regarder la categorie d'arme?*/
      case ITEM_TYPES.competencecreature:
        return arme.system.iscombat && RdDItemCompetenceCreature.isParade(arme)
    }
    return false
  }

  static corpsACorps(actor) {
    let competence = actor?.getCompetenceCorpsACorps() ?? BASE_CORPS_A_CORPS
    let melee = actor ? actor.system.carac['melee'].value : 0
    return {
      _id: competence.id,
      name: 'Corps à corps',
      type: ITEM_TYPES.arme,
      img: competence.img,
      system: {
        initiative: RdDCombatManager.calculInitiative(competence.system.niveau, melee),
        equipe: true,
        rapide: true,
        force: 0,
        dommages: "0",
        dommagesReels: 0,
        mortalite: 'non-mortel',
        competence: 'Corps à corps',
        resistance: 1,
        baseInit: 4,
        cac: 'pugilat',
        deuxmains: true,
        categorie_parade: 'sans-armes'
      }
    }
  }

  static mainsNues(actor) {
    const mainsNues = RdDItemArme.corpsACorps(actor)
    mainsNues.name = 'Mains nues'
    return mainsNues;
  }

  static empoignade(actor) {
    const empoignade = RdDItemArme.corpsACorps(actor)
    empoignade.name = 'Empoignade'
    empoignade.system.cac = 'empoignade'
    empoignade.system.baseInit = 3
    empoignade.system.mortalite = 'empoignade'
    return empoignade
  }
}