import { ITEM_TYPES, RDD_CONFIG, renderTemplate } from "./constants.js";
import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, CATEGORIES_COMPETENCES, CATEGORIES_COMPETENCES_CREATURES } from "./item/base-items.js";
import { ITEM_ACTIONS, DEFAULT_ACTIONS, COMMON_ACTIONS } from "./item/item-actions.js";

import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
import { DialogItemVente } from "./achat-vente/dialog-item-vente.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { RdDUtility } from "./rdd-utility.js";
import { SystemCompendiums } from "./settings/system-compendiums.js";
import { RdDRaretes } from "./item/raretes.js";

const typesInventaireMateriel = [
  ITEM_TYPES.arme,
  ITEM_TYPES.armure,
  ITEM_TYPES.conteneur,
  ITEM_TYPES.faune,
  ITEM_TYPES.gemme,
  ITEM_TYPES.herbe,
  ITEM_TYPES.plante,
  ITEM_TYPES.ingredient,
  ITEM_TYPES.livre,
  ITEM_TYPES.monnaie,
  ITEM_TYPES.munition,
  ITEM_TYPES.nourritureboisson,
  ITEM_TYPES.objet,
  ITEM_TYPES.potion,
]
const typesInventaire = {
  materiel: typesInventaireMateriel,
  all: [ITEM_TYPES.service].concat(typesInventaireMateriel),
}

const typesObjetsOeuvres = [ITEM_TYPES.oeuvre, ITEM_TYPES.recettecuisine, ITEM_TYPES.musique, ITEM_TYPES.chant, ITEM_TYPES.danse, ITEM_TYPES.jeu]
const typesObjetsDraconiques = [ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.souffle, ITEM_TYPES.tete, ITEM_TYPES.signedraconique, ITEM_TYPES.sortreserve, ITEM_TYPES.rencontre]
const typesObjetsConnaissance = [ITEM_TYPES.meditation, ITEM_TYPES.recettealchimique, ITEM_TYPES.sort]
const typesObjetsEffet = [ITEM_TYPES.possession, ITEM_TYPES.poison, ITEM_TYPES.maladie, ITEM_TYPES.blessure]
const typesObjetsCompetence = [ITEM_TYPES.competence, ITEM_TYPES.competencecreature]
const typesAppreciable = [
  ITEM_TYPES.oeuvre, ITEM_TYPES.musique, ITEM_TYPES.chant, ITEM_TYPES.danse, ITEM_TYPES.nourritureboisson,
  ITEM_TYPES.jeu, ITEM_TYPES.service
]
const typesObjetsTemporels = [ITEM_TYPES.blessure, ITEM_TYPES.poison, ITEM_TYPES.maladie, ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.souffle, ITEM_TYPES.signedraconique, ITEM_TYPES.rencontre]
const typesObjetsEquipable = [ITEM_TYPES.arme, ITEM_TYPES.armure, ITEM_TYPES.objet];
const typesEnvironnement = typesInventaireMateriel;
const encBrin = 0.00005; // un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc

export const defaultItemImg = {
  arme: "systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_gnome.webp",
  armure: "systems/foundryvtt-reve-de-dragon/icons/armes_armures/armure_plaques.webp",
  chant: "systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp",
  competence: "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp",
  competencecreature: "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp",
  conteneur: "systems/foundryvtt-reve-de-dragon/icons/objets/sac_a_dos.webp",
  danse: "systems/foundryvtt-reve-de-dragon/icons/arts/danse_0.webp",
  empoignade: "systems/foundryvtt-reve-de-dragon/icons/empoignade.webp",
  extraitpoetique: "systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp",
  faune: "systems/foundryvtt-reve-de-dragon/icons/faune/rongeur.webp",
  gemme: "systems/foundryvtt-reve-de-dragon/icons/gemmes/almaze.webp",
  herbe: "systems/foundryvtt-reve-de-dragon/icons/botanique/Endorlotte.webp",
  ingredient: "systems/foundryvtt-reve-de-dragon/icons/objets/sable_poudre.webp",
  jeu: "systems/foundryvtt-reve-de-dragon/icons/arts/jeux_petasse.webp",
  livre: "systems/foundryvtt-reve-de-dragon/icons/objets/livre.webp",
  maladie: "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/maladie.webp",
  meditation: "systems/foundryvtt-reve-de-dragon/icons/meditations_ecrits/meditation_alchimie.webp",
  musique: "systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp",
  nourritureboisson: "systems/foundryvtt-reve-de-dragon/icons/objets/provision_crue.webp",
  oeuvre: "systems/foundryvtt-reve-de-dragon/icons/competence_comedie.webp",
  ombre: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp",
  poison: "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/venin.webp",
  possession: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
  potion: "systems/foundryvtt-reve-de-dragon/icons/objets/liqueur_de_bagdol.webp",
  queue: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp",
  recettealchimique: "systems/foundryvtt-reve-de-dragon/icons/competence_alchimie.webp",
  recettecuisine: "systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_1.webp",
  rencontre: "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp",
  service: "systems/foundryvtt-reve-de-dragon/icons/services/lit.webp",
  signedraconique: "systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp",
  sort: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
  sortreserve: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
  souffle: "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp",
  tache: "systems/foundryvtt-reve-de-dragon/assets/actions/tache.svg",
  tarot: "systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.webp",
  tete: "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp",
  monnaie: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp",
  munition: "systems/foundryvtt-reve-de-dragon/icons/objets/fleche.webp"
}

const ITEM_TYPES_PLURIEL = {
  [ITEM_TYPES.jeu]: 'jeux'
}

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

  static get defaultIcon() {
    return undefined;
  }

  static getDefaultImg(itemType) {
    return game.system.rdd.itemClasses[itemType]?.defaultIcon ?? defaultItemImg[itemType];
  }

  static isFieldInventaireModifiable(type, field) {
    switch (field) {
      case 'quantite':
        if (ITEM_TYPES.conteneur == type) {
          return false
        }
        break;
      case 'cout':
        if (ITEM_TYPES.monnaie == type) {
          return game.user.isGM;
        }
        break
    }
    return true;
  }

  static itemTypePluriel(type) {
    if (ITEM_TYPES[type]) {
      return ITEM_TYPES_PLURIEL[type] ?? (type + 's')
    }
    console.error(`Item type ${type} is undefined`)
    return type
  }
  static async getCorrespondingItem(itemRef) {
    if (itemRef.pack) {
      return await SystemCompendiums.loadDocument(itemRef)
    }
    return game.items.get(itemRef.id ?? itemRef._id);
  }

  static getItemTypesInventaire(mode = 'materiel') {
    return typesInventaire[mode ?? 'materiel']
  }

  static getItemTypesDraconiques() {
    return typesObjetsDraconiques;
  }

  static getItemTypesEnvironnement() {
    return typesEnvironnement;
  }

  static getTypesOeuvres() {
    return typesObjetsOeuvres
  }

  static getCategories(itemType) {
    switch (itemType) {
      case ITEM_TYPES.competence:
        return CATEGORIES_COMPETENCES
      case ITEM_TYPES.competencecreature:
        return CATEGORIES_COMPETENCES_CREATURES
    }
    return {}
  }

  constructor(docData, context = {}) {
    if (!context.rdd?.ready) {
      foundry.utils.mergeObject(context, { rdd: { ready: true } });
      const ItemConstructor = game.system.rdd.itemClasses[docData.type];
      if (ItemConstructor) {
        if (!docData.img) {
          docData.img = ItemConstructor.defaultIcon;
        }
        return new ItemConstructor(docData, context);
      }
    }
    if (!docData.img) {
      docData.img = RdDItem.getDefaultImg(docData.type);
    }
    context.rdd = undefined
    super(docData, context);
  }

  async _preCreate(data, options, user) {
    await this.parent?.delayedRenderSheet('_preCreateItem', data, options)
    return super._preCreate(data, options, user)
  }

  async _preUpdate(changed, options, user) {
    await this.parent?.delayedRenderSheet('_preUpdateItem', changed, options)
    return super._preUpdate(changed, options, user)
  }

  async _preDelete(options, user) {
    await this.parent?.delayedRenderSheet('_preDeleteItem', { id: this.id }, options)
    return super._preDelete(options, user)
  }

  getUniteQuantite() {
    switch (this.type) {
      case ITEM_TYPES.monnaie: return "(Pièces)"
      case ITEM_TYPES.herbe:
        switch (this.system.categorie) {
          case 'Alchimie': case 'Repos': case 'Soin':
            return "(Brins)"
          case 'Cuisine': return '';
        }
        return '';
      case ITEM_TYPES.ingredient: return "(Pépins ou Brins)"
    }
    return '';
  }

  isEquipable() {
    return typesObjetsEquipable.includes(this.type)
  }

  isCompetencePersonnage() { return this.type == ITEM_TYPES.competence }
  isCompetenceCreature() { return this.type == ITEM_TYPES.competencecreature }
  isConteneur() { return this.type == ITEM_TYPES.conteneur }
  findConteneur() {
    if (this.isInventaire('all') && this.parent) {
      return this.parent.findConteneur(this)
    }
    return undefined
  }

  isMonnaie() { return this.type == ITEM_TYPES.monnaie }
  isNourritureBoisson() { return this.type == ITEM_TYPES.nourritureboisson; }
  isService() { return this.type == ITEM_TYPES.service }
  isAttaque() { return false }
  isParade() { return false }
  isBouclier() { return false }
  getCategorieAttaque() { return undefined }
  isCompetence() { return typesObjetsCompetence.includes(this.type) }
  isEsquive() {
    return (this.isCompetence()
      && this.system.categorie == 'melee'
      && Grammar.includesLowerCaseNoAccent(this.name, BASE_ESQUIVE.name));
  }

  isCorpsACorps() {
    return this.isCompetence()
      && this.system.categorie == 'melee'
      && Grammar.includesLowerCaseNoAccent(this.name, BASE_CORPS_A_CORPS.name)
  }

  isCompetenceArme() {
    return this.isCompetence()
      && ['melee', 'tir', 'lancer'].includes(this.system.categorie)
      && !this.isEsquive()
  }

  isCompetencePossession() { return ITEM_TYPES.competencecreature == this.type && this.system.categorie == CATEGORIES_COMPETENCES_CREATURES.possession.key }
  isTemporel() { return typesObjetsTemporels.includes(this.type) }
  isOeuvre() { return typesObjetsOeuvres.includes(this.type) }
  isDraconique() { return RdDItem.getItemTypesDraconiques().includes(this.type) }
  isQueueDragon() { return [ITEM_TYPES.queue, ITEM_TYPES.ombre].includes(this.type) }
  isEffet() { return typesObjetsEffet.includes(this.type) }
  isConnaissance() { return typesObjetsConnaissance.includes(this.type) }

  isInventaire(mode = 'materiel') { return RdDItem.getItemTypesInventaire(mode).includes(this.type); }
  isAppreciable() { return typesAppreciable.includes(this.type) }
  isBoisson() { return this.isNourritureBoisson() && this.system.boisson; }
  isAlcool() { return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise; }
  isHerbeAPotion() { return this.type == ITEM_TYPES.herbe && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); }
  isBlessure() { return this.type == ITEM_TYPES.blessure }

  isPresentDansMilieux(milieux) {
    return this.getEnvironnements(milieux).length > 0
  }

  get nameDisplay() {
    return this.isMagique ? (this.name + ' <i class="fa-solid fa-sparkles"></i>') : this.name
  }

  get isEnchantementPossible() { return false }

  getEnvironnements(milieux = undefined) {
    const environnements = this.isInventaire() ? this.system.environnement : undefined;
    if (milieux == undefined || !environnements) {
      return environnements ?? [];
    }
    return environnements.filter(env => milieux.includes(env.milieu))
  }

  getMilieux() {
    return this.getEnvironnements().map(env => env.milieu);
  }

  getRaretes(milieux = undefined) {
    if (this.isInventaire()) {
      const raretes = this.getEnvironnements(milieux).map(env => RdDRaretes.byCode(env.rarete));
      if (milieux == undefined && raretes.length == 0) {
        return [RdDRaretes.rareteFrequente()];
      }
      return raretes;
    }
    return [RdDRaretes.rareteEgale()];
  }

  getFrequence(milieux = undefined) {
    const frequences = this.getEnvironnements(milieux).map(it => it.frequence);
    return frequences.length == 0 ? 0 : Math.max(...frequences);
  }

  getItemGroup() {
    if (this.isInventaire()) return "equipement";
    if (this.isOeuvre()) return "oeuvre";
    if (this.isDraconique()) return "draconique";
    if (this.isConnaissance()) return "connaissance";
    if (this.isEffet()) return "effet";
    if (this.isCompetence()) return "competence";
    return "autres";
  }

  isConteneurNonVide() { return this.isConteneur() && (this.system.contenu?.length ?? 0) > 0; }
  isConteneurVide() { return this.isConteneur() && (this.system.contenu?.length ?? 0) == 0; }
  isVideOuNonConteneur() { return !this.isConteneur() || (this.system.contenu?.length ?? 0) == 0; }

  isFinPeriode(oldTimestamp, newTimestamp) {
    if (!this.isTemporel()) {
      return false;
    }
    const finPeriode = new RdDTimestamp(this.system.temporel.fin);
    return oldTimestamp.compare(finPeriode) < 0 && finPeriode.compare(newTimestamp) <= 0
  }

  async onCreateItemTemporel(actor) {
    if (this.isTemporel()) {
      const timestampDebut = game.system.rdd.calendrier.timestamp;
      const timestampFin = await this.calculerFinPeriodeTemporel(timestampDebut);
      await actor.updateEmbeddedDocuments('Item', [{
        _id: this.id,
        'system.temporel.debut': foundry.utils.deepClone(timestampDebut),
        'system.temporel.fin': foundry.utils.deepClone(timestampFin),
      }])
    }
  }

  async calculerFinPeriodeTemporel(timestampDebut) {
    return timestampDebut;
  }

  async onFinPeriodeTemporel(oldTimestamp, newTimestamp) {
    if (this.isTemporel() && this.actor) {
      await this.onFinPeriode(oldTimestamp, newTimestamp);
    }
  }

  async onFinPeriode(oldTimestamp, newTimestamp) {
    console.log(`${this.actor.name}: l'objet ${this.name} a expiré et été supprimé`);
    await this.actor?.deleteEmbeddedDocuments('Item', [this.id]);
  }

  getUtilisation() {
    switch (this.type) {
      case ITEM_TYPES.nourritureboisson: return 'cuisine';
      case ITEM_TYPES.herbe: case ITEM_TYPES.faune: case ITEM_TYPES.ingredient: case ITEM_TYPES.plante:
        switch (this.system.categorie) {
          case 'Cuisine': return 'cuisine';
          case 'Toxique': case 'Poison': return 'poison';
          case 'Alchimie': return 'alchimie'
          case 'Soin': case 'Repos': return 'soins'
        }
        return this.system.sust > 0 ? 'cuisine' : '';
    }
    return '';
  }

  getUtilisationCuisine() {
    if (this.getUtilisation() == 'cuisine') {
      switch (this.type) {
        case ITEM_TYPES.nourritureboisson:
          return 'pret';
        case ITEM_TYPES.herbe: case ITEM_TYPES.faune: case ITEM_TYPES.ingredient: case ITEM_TYPES.plante:
          return 'brut';
      }
    }
    return '';
  }

  isCristalAlchimique() {
    return this.type == ITEM_TYPES.objet && Grammar.includesLowerCaseNoAccent(this.name, 'cristal alchimique') && this.system.quantite > 0;
  }

  get isMagique() {
    return this.system.magique
  }

  isItemCommerce() {
    return this.parent?.type == 'commerce';
  }

  isNomLike(texte) {
    return Grammar.includesLowerCaseNoAccent(this.name, texte)
  }

  isNomTypeLike(texte) {
    return this.isNomLike(texte) || Grammar.includesLowerCaseNoAccent(Misc.typeName(this.type, 'Item'), texte)
  }

  getQuantite() {
    return this.isService() ? undefined : Math.round(this.system.quantite ?? 0)
  }

  getEncTotal() {
    return (this.getQuantite() ?? 0) * this.getEnc();
  }

  getEnc() {
    switch (this.type) {
      case ITEM_TYPES.service:
        return 0
      case ITEM_TYPES.herbe:
        return this.getEncHerbe()
    }
    return Math.max(this.system.encombrement ?? 0.0, 0.0);
  }

  getEncContenu() {
    return this.getContenu()
      .map(it => it.getRecursiveEnc())
      .reduce(Misc.sum(), 0);
  }

  getRecursiveEnc() {
    return this.getEncTotal() + this.getEncContenu()
  }

  getEncHerbe() {
    switch (this.system.categorie) {
      case 'Repos': case 'Soin': case 'Alchimie':
        return encBrin
    }
    return this.system.encombrement

  }

  getContenu() {
    if (this.isConteneur()) {
      return this.system.contenu.map(idContenu => this.actor.getItem(idContenu));
    }
    return []
  }

  isConteneurContenu(conteneur) {
    return this.getContenu()
      .find(it => it.id == conteneur.id || it.isConteneurContenu(conteneur))
  }

  valeurTotale() {
    return (this.isService() ? 1 : this.getQuantite()) * this.valeur()
  }

  valeur() {
    return this.system.cout ?? 0
  }

  calculerPrixCommercant() {
    if (this.isItemCommerce()) {
      // appliquer le pourcentage
      return this.parent.calculerPrix(this);
    }
    return this.system.cout
  }

  prepareDerivedData() {
    super.prepareDerivedData();
    if (this.isInventaire()) {
      this.system.encTotal = this.getEncTotal()
    }
    this.equipable = this.isEquipable()
  }

  itemActions() {
    return COMMON_ACTIONS.concat(this.itemSpecificActions()).concat(DEFAULT_ACTIONS)
  }

  itemSpecificActions() {
    const actions = ITEM_ACTIONS[this.type] ?? []
    return actions
  }

  isActionAllowed(code) {
    switch (this.type) {
      case ITEM_TYPES.possession:
      case ITEM_TYPES.empoignade:
      case ITEM_TYPES.rencontre:
      case ITEM_TYPES.signedraconique:
        switch (code) {
          case 'item-edit':
          case 'item-delete':
            return game.user.isGM
        }
      case ITEM_TYPES.maladie:
      case ITEM_TYPES.poison:
        return game.user.isGM
      case ITEM_TYPES.casetmr:
        switch (code) {
          case 'item-delete':
            return game.user.isGM
        }
    }
    return true
  }

  async diminuerQuantite(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) {
    if (options.diminuerQuantite == false) return;
    await this.quantiteIncDec(-nombre, options);
  }

  async onCreateDecoupeComestible(actor) {
    if (actor && this.getUtilisationCuisine() == 'brut' && this.system.sust != 1) {
      if (this.system.sust < 1) {
        await actor.updateEmbeddedDocuments('Item', [{
          _id: this.id,
          'system.sust': 0
        }])
      }
      else {
        const sust = Math.floor(this.system.sust);
        await actor.updateEmbeddedDocuments('Item', [{
          _id: this.id,
          'system.quantite': this.system.quantite * sust,
          'system.encombrement': Misc.keepDecimals(this.system.encombrement / sust, 2),
          'system.cout': Math.max(0, Misc.keepDecimals(this.system.cout / sust, 2)),
          'system.sust': 1
        }])
      }
    }
  }

  async empiler(item) {
    if (this.getUtilisationCuisine() == 'brut') {
      const sust = this.system.sust + item.system.sust;
      const encombrement = this.system.encombrement + item.system.encombrement;
      await this.update({
        "system.sust": sust,
        "system.encombrement": encombrement
      });
    }
    else {
      await this.quantiteIncDec(item.system.quantite);
    }
    // TODO: suppression dans les conteneurs!
    await item.delete();
  }

  async quantiteIncDec(nombre, options = { supprimerSiZero: false }) {
    const quantite = Number(this.system.quantite ?? -1);
    if (quantite >= 0) {
      const reste = Math.max(quantite + Number(nombre), 0);

      if (reste == 0) {
        if (options.supprimerSiZero) {
          ui.notifications.notify(`${this.name} supprimé de votre équipement`);
          await this.delete();
        }
        else {
          ui.notifications.notify(`Il ne vous reste plus de ${this.name}, vous pouvez le supprimer de votre équipement, ou trouver un moyen de vous en procurer.`);
          await this.update({ "system.quantite": 0 });
        }
      }
      else {
        await this.update({ "system.quantite": reste });
      }
    }
  }

  /* -------------------------------------------- */
  // détermine si deux équipements sont similaires: de même type, et avec les même champs hormis la quantité
  isInventaireEmpilable(other) {
    if (!other || !this.isInventaire()) {
      return [false, undefined];
    }
    if (this.isConteneur()) {
      return [false, `Impossible de regrouper des conteneurs, ils ne sont pas empilables`];
    }
    if (this.system.quantite == undefined) {
      return [false, `Impossible de regrouper des ${this.type}, ils ne sont pas empilables`];
    }
    else if (this.type != other.type) {
      return [false, `Impossible de regrouper des ${this.type} avec des ${other.type}`];
    }
    else if (this.name != other.name) {
      return [false, `Impossible de regrouper ${this.name} avec ${other.name}`];
    }
    else {
      const excludedProperties = ['quantite', 'cout', 'encTotal', 'environnement', 'contenu'];
      if (this.getUtilisationCuisine()) {
        excludedProperties.push('sust', 'encombrement');
      }
      let differences = Object.entries(this.system)
        .filter(([key, value]) => !excludedProperties.includes(key))
        .filter(([key, value]) => value != other.system[key])
      if (differences.length > 0) {
        let message = `Impossible de regrouper les ${this.type} ${this.name}: `;
        for (const [key, value] of differences) {
          message += `<br>${key}: ${value} vs ${other.system[key]}`;
        }
        return [false, message];
      }
    }
    return [true, undefined];
  }

  async proposerVente(quantiteMax = undefined) {
    console.log(this);
    if (this.isConteneurNonVide()) {
      ui.notifications.warn(`Votre ${this.name} n'est pas vide, pas possible de le proposer`);
      return;
    }
    await DialogItemVente.display({ item: this, quantiteMax })
  }

  /* -------------------------------------------- */
  getProprietes() {
    if (this[`_${this.type}ChatData`]) {
      return this[`_${this.type}ChatData`]().filter(it => it != undefined);
    }
    return [];
  }

  /* -------------------------------------------- */
  async postItemToChat(modeOverride) {
    console.log(this);
    let chatData = {
      doctype: 'Item',
      id: this.id,
      type: this.type,
      img: this.img,
      pack: this.pack,
      name: this.name,
      actor: this.actor ? { id: this.actor.id } : undefined,
      system: { description: this.system.description },
      properties: this.getProprietes(),
    }
    renderTemplate(this.getChatItemTemplate(), chatData).then(async html => {
      let chatOptions = RdDUtility.chatDataSetup(html, modeOverride);
      await ChatMessage.create(chatOptions)
    })
  }

  getChatItemTemplate() {
    return 'systems/foundryvtt-reve-de-dragon/templates/post-item.hbs'
  }

  async postItemToChatCompact(modeOverride) {
    const typeLabel = game.i18n.localize(`TYPES.Item.${this.type}`)
    const stats = this.getProprietes().slice(0, 3)
    const isInventaire = RdDItem.getItemTypesInventaire('all').includes(this.type)
    let chatData = {
      doctype: 'Item',
      id: this.id,
      type: this.type,
      img: this.img,
      pack: this.pack,
      name: this.name,
      actor: this.actor ? { id: this.actor.id } : undefined,
      typeLabel,
      encombrement: isInventaire ? (this.system.encombrement ?? 0) : undefined,
      cout: isInventaire ? (this.system.cout ?? 0) : undefined,
      quantite: isInventaire ? (this.getQuantite() ?? 1) : undefined,
      stats
    }
    const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-item-compact.hbs', chatData)
    let chatOptions = RdDUtility.chatDataSetup(html, modeOverride);
    await ChatMessage.create(chatOptions)
  }

  static propertyIfDefined(name, val, condition = true) {
    return condition ? `<b>${name}</b>: ${val}` : undefined;
  }

  _inventaireTemplateChatData() {
    return [
      RdDItem.propertyIfDefined('Qualité', this.system.qualite, this.system.qualite != 0),
      RdDItem.propertyIfDefined('Encombrement', this.system.encombrement)
      // cout et quantité masqués
    ]
  }
  /* -------------------------------------------- */
  _objetChatData() {
    return this._inventaireTemplateChatData()
  }

  /* -------------------------------------------- */
  _nourritureboissonChatData() {
    return [
      RdDItem.propertyIfDefined('Sustentation', this.system.sust, this.system.sust > 0),
      RdDItem.propertyIfDefined('Désaltère', this.system.desaltere, this.system.boisson),
      RdDItem.propertyIfDefined('Force alcool', this.system.force, this.system.boisson && this.system.alcoolise),
      RdDItem.propertyIfDefined('Exotisme', this.system.exotisme, this.system.exotisme < 0),
      ...this._inventaireTemplateChatData()
    ]
  }
  /* -------------------------------------------- */
  _armeChatData() {
    return [
      `<b>Compétence</b>: ${this.system.competence}`,
      `<b>Dommages</b>: ${this.system.dommages} ${this.system.mortalite == RDD_CONFIG.encaissement.nonmortel ? '(Non mortel)' : ''}`,
      `<b>Force minimum</b>: ${this.system.force}`,
      `<b>Resistance</b>: ${this.system.resistance}`,
      ...this._inventaireTemplateChatData()
    ]
  }
  /* -------------------------------------------- */
  _conteneurChatData() {
    return [
      `<b>Capacité</b>: ${this.system.capacite} Enc.`,
      ...this._inventaireTemplateChatData()
    ]
  }
  /* -------------------------------------------- */
  _munitionChatData() {
    return this._inventaireTemplateChatData()
  }
  /* -------------------------------------------- */
  _armureChatData() {
    return [
      `<b>Protection</b>: ${this.system.protection}`,
      `<b>Détérioration</b>: ${this.system.deterioration}`,
      `<b>Malus armure</b>: ${this.system.malus}`,
      ...this._inventaireTemplateChatData()
    ]
  }
  /* -------------------------------------------- */
  _competenceChatData() {
    return [
      `<b>Catégorie</b>: ${this.system.categorie}`,
      `<b>Niveau</b>: ${this.system.niveau}`,
      `<b>Caractéristique par défaut</b>: ${this.system.carac_defaut}`,
      `<b>XP</b>: ${this.system.xp}`
    ]
  }
  /* -------------------------------------------- */
  _competencecreatureChatData() {
    return [
      `<b>Catégorie</b>: ${this.system.categorie}`,
      `<b>Niveau</b>: ${this.system.niveau}`,
      `<b>Caractéristique</b>: ${this.system.carac_value}`,
      `<b>XP</b>: ${this.system.xp}`
    ]
  }
  /* -------------------------------------------- */
  _sortChatData() {
    return [
      `<b>Draconic</b>: ${this.system.draconic}`,
      `<b>Difficulté</b>: ${this.system.difficulte}`,
      `<b>Case TMR</b>: ${this.system.caseTMR}`,
      `<b>Points de Rêve</b>: ${this.system.ptreve}`
    ]
  }
  /* -------------------------------------------- */
  _herbeChatData() {
    return [
      `<b>Milieu</b>: ${this.system.milieu}`,
      `<b>Catégorie</b>: ${this.system.categorie}`,
      ...this._inventaireTemplateChatData()
    ]
  }
  /* -------------------------------------------- */
  _ingredientChatData() {
    return [
      `<b>Milieu</b>: ${this.system.milieu}`,
      `<b>Catégorie</b>: ${this.system.categorie}`,
      ...this._inventaireTemplateChatData()
    ]
  }
  /* -------------------------------------------- */
  _fauneChatData() {
    return [
      `<b>Sustentation</b>: ${this.system.sust}`,
      `<b>Milieu</b>: ${this.system.milieu}`,
      ...this._inventaireTemplateChatData()
    ]
  }
  /* -------------------------------------------- */
  _tacheChatData() {
    return [
      `<b>Caractéristique</b>: ${this.system.carac}`,
      `<b>Compétence</b>: ${this.system.competence}`,
      `<b>Périodicité</b>: ${this.system.periodicite}`,
      `<b>Fatigue</b>: ${this.system.fatigue}`,
      `<b>Difficulté</b>: ${this.system.difficulte}`,
      RdDItem.propertyIfDefined('Points de Tâche', this.system.points_de_tache, !this.system.cacher_points_de_tache),
      `<b>Points de Tâche atteints</b>: ${this.system.points_de_tache_courant}`]
  }
  /* -------------------------------------------- */
  _livreChatData() {
    return [
      `<b>Compétence</b>: ${this.system.competence}`,
      `<b>Auteur</b>: ${this.system.auteur}`,
      `<b>Difficulté</b>: ${this.system.difficulte}`,
      RdDItem.propertyIfDefined('Points de Tâche', this.system.points_de_tache, !this.system.cacher_points_de_tache),
      ...this._inventaireTemplateChatData()
    ]
  }
  /* -------------------------------------------- */
  _queueChatData() {
    function label(categorie) {
      switch (categorie) {
        case 'ideefixe': return 'Idée fixe';
        case 'lancinant': return 'Désir lancinant';
      }
      return ''
    }
    return [
      `<b>Refoulement</b>: ${this.system.refoulement}`,
      `<b>Catégorie</b>: ${label(this.system.categorie)}`,
      `<b>Affecte</b>: ${this.system.hautrevant ? 'les haut-rêvants' : 'tout le monde'}`,
    ]
  }
  /* -------------------------------------------- */
  _ombreChatData() {
    return this._queueChatData()
  }
  /* -------------------------------------------- */
  _souffleChatData() {
    return [
      `<b>Affecte</b>: ${this.system.hautrevant ? 'les haut-rêvants' : 'tout le monde'}`,
    ];
  }
  /* -------------------------------------------- */
  _teteChatData() {
    return [
      `<b>Affecte</b>: ${this.system.hautrevant ? 'les haut-rêvants' : 'tout le monde'}`,
    ];
  }
  /* -------------------------------------------- */
  _tarotChatData() {
    return [
      RdDItem.propertyIfDefined('Carte', RdDUtility.linkCompendium(this.pack, this.id, this.name), this.pack),
      `<b>Concept</b>: ${this.system.concept}`,
      `<b>Aspect</b>: ${this.system.aspect}`,
    ]
  }
  /* -------------------------------------------- */
  _nombreastralChatData() {
    return [
      `<b>Valeur</b>: ${this.system.value}`,
      `<b>Jour</b>: ${this.system.jourlabel}`,
    ]
  }
  /* -------------------------------------------- */
  _monnaieChatData() {
    return this._inventaireTemplateChatData()
  }
  /* -------------------------------------------- */
  _meditationChatData() {
    return [
      `<b>Thème</b>: ${this.system.theme}`,
      `<b>Compétence</b>: ${this.system.competence}`,
      `<b>Support</b>: ${this.system.support}`,
      `<b>Heure</b>: ${this.system.heure}`,
      `<b>Purification</b>: ${this.system.purification}`,
      `<b>Vêture</b>: ${this.system.veture}`,
      `<b>Comportement</b>: ${this.system.comportement}`,
      `<b>Case TMR</b>: ${this.system.tmr}`
    ]
  }
  /* -------------------------------------------- */
  _rencontreChatData() {
    if (this.system.coord) {
      return [
        `<b>Force</b>: ${this.system.force}`,
        `<b>Coordonnées</b>: ${this.system.coord}`,
      ]
    }
    return [
      `<b>Force</b>: ${this.system.formule}`,
      `<b>Refoulement</b>: ${this.system.refoulement}`,
      RdDItem.propertyIfDefined('<b>Présent de cités</b>', '', this.system.presentCite),
    ]
  }
  /* -------------------------------------------- */
  _casetmrChatData() {
    return [
      `<b>Coordonnée</b>: ${this.system.coord}`,
      `<b>Spécificité</b>: ${this.system.specific}`
    ]
  }
  /* -------------------------------------------- */
  _maladieChatData() {
    if (!this.system.identifie) {
      return [`<b>Inconnue</b>`]
    }
    return [
      `<b>Malignité</b>: ${this.system.malignite}`,
      `<b>Périodicité</b>: ${this.system.periodicite}`,
      `<b>Dommages</b>: ${this.system.dommages}`,
      RdDItem.propertyIfDefined('<b>Remedes</b>', this.system.remedes, this.system.remedesconnus),
    ]
  }

  /* -------------------------------------------- */
  _poisonChatData() {
    return this._maladieChatData();
  }

  /* -------------------------------------------- */
  _gemmeChatData() {
    return [
      `<b>Pureté</b>: ${this.system.purete}`,
      `<b>Taille</b>: ${this.system.taille}`,
      `<b>Inertie</b>: ${this.system.inertie}`,
      `<b>Enchantabilité</b>: ${this.system.enchantabilite}`,
      ...this._inventaireTemplateChatData()
    ]
  }
  /* -------------------------------------------- */
  _recettealchimiqueChatData() {
    const ingredients = Misc.safeJsonParse(this.system.ingredients, []);
    const resultat = Misc.safeJsonParse(this.system.resultat, {});
    const resultatStr = resultat.name
      ? `${resultat.quantite || 1}× ${resultat.name} (${resultat.type || 'objet'})`
      : null;
    return [
      RdDItem.propertyIfDefined('But', this.system.but),
      ...ingredients.slice(0, 8).map(i => `• ${i.nom}${i.quantite > 1 ? ` ×${i.quantite}` : ''}`),
      ingredients.length > 8 ? `<i>…et ${ingredients.length - 8} autres</i>` : undefined,
      resultatStr ? `<b>Résultat</b>: ${resultatStr}` : undefined,
    ]
  }
  /* -------------------------------------------- */
  _recettecuisineChatData() {
    return [
      RdDItem.propertyIfDefined('Niveau', this.system.niveau, this.system.niveau > 0),
      RdDItem.propertyIfDefined('Durée', this.system.duree),
      RdDItem.propertyIfDefined('Sust', this.system.sust, this.system.sust > 0),
      RdDItem.propertyIfDefined('Exotisme', this.system.exotisme, this.system.exotisme !== 0),
      RdDItem.propertyIfDefined('Référence', this.system.reference),
    ]
  }
  /* -------------------------------------------- */
  _chantChatData() {
    return [
      RdDItem.propertyIfDefined('Niveau', this.system.niveau, this.system.niveau > 0),
      RdDItem.propertyIfDefined('Référence', this.system.reference),
    ]
  }
  /* -------------------------------------------- */
  _musiqueChatData() {
    return [
      RdDItem.propertyIfDefined('Niveau', this.system.niveau, this.system.niveau < 0),
      RdDItem.propertyIfDefined('Référence', this.system.reference),
    ]
  }
  /* -------------------------------------------- */
  _danseChatData() {
    return [
      RdDItem.propertyIfDefined('Type', this.system.type),
      RdDItem.propertyIfDefined('Agilité', 'Oui', this.system.agilite),
      RdDItem.propertyIfDefined('Apparence', 'Oui', this.system.apparence),
      RdDItem.propertyIfDefined('Niveau', this.system.niveau, this.system.niveau > 0),
      RdDItem.propertyIfDefined('Référence', this.system.reference),
    ]
  }
  /* -------------------------------------------- */
  _jeuChatData() {
    return [
      RdDItem.propertyIfDefined('Type', this.system.type),
      RdDItem.propertyIfDefined('Base', this.system.base),
      RdDItem.propertyIfDefined('Carac/Comp', this.system.caraccomp),
      RdDItem.propertyIfDefined('Référence', this.system.reference),
    ]
  }
}
