import { STRING, HTMLSTRING, MODEL_ARRAY } from "../common/field-types.mjs";
import { statField, santeField, attributField, compteurField, compteurMaxField } from "./_actor-helpers.mjs";
import { ITEM_TYPES } from "../constants.js";
import { RdDItemRace } from "../item/race.js";
import { RdDCarac } from "../rdd-carac.js";
import RdDItemTete from "../documents/tete.mjs";
import { Misc } from "../misc.js";

const fields = foundry.data.fields;

export default class RdDModelPersonnage extends foundry.abstract.TypeDataModel {
  static defineSchema() {
    return {
      carac: new fields.SchemaField({
        taille: statField(10, "Taille"),
        apparence: statField(10, "Apparence"),
        constitution: statField(10, "Constitution"),
        force: statField(10, "Force"),
        agilite: statField(10, "Agilité"),
        dexterite: statField(10, "Dextérité"),
        vue: statField(10, "Vue"),
        ouie: statField(10, "Ouïe"),
        odoratgout: statField(10, "Odorat-Goût"),
        volonte: statField(10, "Volonté"),
        intellect: statField(10, "Intellect"),
        empathie: statField(10, "Empathie"),
        reve: statField(10, "Rêve"),
        chance: statField(10, "Chance"),
        melee: statField(10, "Mêlée", true),
        tir: statField(10, "Tir", true),
        lancer: statField(10, "Lancer", true),
        derobee: statField(10, "Dérobée", true),
      }),
      sante: new fields.SchemaField({
        vie: santeField(10, 10, "Vie", true),
        endurance: santeField(10, 10, "Endurance", true),
        fatigue: santeField(0, 0, "Fatigue", true),
        bonusPotion: new fields.NumberField({ initial: 0, integer: true }),
      }),
      attributs: new fields.SchemaField({
        sconst: attributField(0, "S. Const", true),
        sust: attributField(0, "Sustentation", true),
        plusdom: attributField(0, "+dom", true),
        encombrement: attributField(0.0, "Encombrement", true),
        protection: attributField(0, "Protection naturelle", false),
        hautrevant: attributField("", "Haut rêvant", true, true),
      }),
      reve: new fields.SchemaField({
        reve: new fields.SchemaField({
          value: new fields.NumberField({ initial: 10, integer: true }),
          max: new fields.NumberField({ initial: 0, integer: true }),
          label: new fields.StringField({ initial: "Points de Rêve actuels" }),
          thanatosused: new fields.BooleanField({ initial: false }),
        }),
        seuil: new fields.SchemaField({
          value: new fields.NumberField({ initial: 10, integer: true }),
          max: new fields.NumberField({ initial: 0, integer: true }),
          label: new fields.StringField({ initial: "Seuil de Rêve" }),
        }),
        tmrpos: new fields.SchemaField({
          coord: new fields.StringField({ initial: "A1" }),
          label: new fields.StringField({ initial: "Position TMR" }),
          cache: new fields.BooleanField({ initial: false }),
        }),
        refoulement: new fields.SchemaField({
          value: new fields.NumberField({ initial: 0, integer: true }),
          label: new fields.StringField({ initial: "Points de Refoulement" }),
        }),
        tmrcarte: new fields.StringField({ initial: "", label: "Carte TMR" }),
      }),
      compteurs: new fields.SchemaField({
        sust: compteurField(0, "Sust.", true),
        eau: compteurField(0, "Eau", true),
        moral: compteurField(0, "Moral", true),
        exaltation: compteurField(0, "Exaltation", true),
        dissolution: compteurField(0, "Dissolution", true),
        chance: compteurMaxField(0, 0, "Chance actuelle"),
        destinee: compteurField(0, "Destinée", true),
        voyage: compteurField(0, "Voyage", true),
        etat: compteurField(0, "Etat général"),
        ethylisme: new fields.SchemaField({
          value: new fields.NumberField({ initial: 1, integer: true }),
          label: new fields.StringField({ initial: "Ethylisme" }),
          isInput: new fields.BooleanField({ initial: true }),
          nb_doses: new fields.NumberField({ initial: 0, integer: true }),
          jet_moral: new fields.BooleanField({ initial: false }),
        }),
        stress: new fields.SchemaField({
          value: new fields.NumberField({ initial: 0, integer: true }),
          label: new fields.StringField({ initial: "Stress" }),
          isStress: new fields.BooleanField({ initial: true }),
          isInput: new fields.BooleanField({ initial: true }),
        }),
        experience: compteurField(0, "Experience", true),
        bonmoments: new fields.ArrayField(
          new fields.SchemaField({
            value: new fields.NumberField({ initial: 0, integer: true }),
            label: new fields.StringField({ initial: "" }),
          }),
          { ...MODEL_ARRAY }
        ),
      }),
      sommeil: new fields.SchemaField({
        nouveaujour: new fields.BooleanField({ initial: false }),
        date: new fields.SchemaField({
          indexDate: new fields.NumberField({ initial: -1, integer: true }),
          indexMinute: new fields.NumberField({ initial: 0, integer: true }),
        }),
        insomnie: new fields.BooleanField({ initial: false }),
        moral: new fields.StringField({ initial: "" }),
        heures: new fields.NumberField({ initial: 0, integer: true }),
      }),
      metier: new fields.StringField({ initial: "", ...STRING }),
      biographie: new fields.HTMLField({ initial: "", ...HTMLSTRING }),
      notes: new fields.HTMLField({ initial: "", ...HTMLSTRING }),
      notesmj: new fields.HTMLField({ initial: "", ...HTMLSTRING }),
      race: new fields.StringField({ initial: "", ...STRING }),
      yeux: new fields.StringField({ initial: "", ...STRING }),
      cheveux: new fields.StringField({ initial: "", ...STRING }),
      taille: new fields.StringField({ initial: "", ...STRING }),
      poids: new fields.StringField({ initial: "", ...STRING }),
      heure: new fields.StringField({ initial: "", ...STRING }),
      sexe: new fields.StringField({ initial: "", ...STRING }),
      age: new fields.StringField({ initial: "", ...STRING }),
      beaute: new fields.NumberField({ initial: 10, integer: true }),
      main: new fields.StringField({ initial: "droitier", ...STRING }),
      experiencelog: new fields.ArrayField(
        new fields.SchemaField({
          date: new fields.NumberField({ initial: 0, integer: true }),
          topic: new fields.StringField({ initial: "", ...STRING }),
          from: new fields.NumberField({ initial: 0, integer: true }),
          to: new fields.NumberField({ initial: 0, integer: true }),
          description: new fields.StringField({ initial: "", ...STRING }),
        }),
        { ...MODEL_ARRAY }
      ),
      subacteurs: new fields.SchemaField({
        suivants: new fields.ArrayField(
          new fields.SchemaField({
            id: new fields.StringField({ initial: "", ...STRING }),
          }),
          { ...MODEL_ARRAY }
        ),
        montures: new fields.ArrayField(
          new fields.SchemaField({
            id: new fields.StringField({ initial: "", ...STRING }),
          }),
          { ...MODEL_ARRAY }
        ),
        vehicules: new fields.ArrayField(
          new fields.SchemaField({
            id: new fields.StringField({ initial: "", ...STRING }),
          }),
          { ...MODEL_ARRAY }
        ),
      }),
      description: new fields.HTMLField({ initial: "", ...HTMLSTRING }),
    };
  }

  prepareDerivedData() {
    const actor = this.parent;

    RdDItemRace.applyRacialLimits(actor);

    this.carac.melee.value = Math.floor((actor.getForce() + Misc.toInt(this.carac.agilite.value)) / 2);
    this.carac.tir.value = Math.floor((Misc.toInt(this.carac.vue.value) + Misc.toInt(this.carac.dexterite.value)) / 2);
    this.carac.lancer.value = Math.floor((Misc.toInt(this.carac.tir.value) + Misc.toInt(this.carac.force.value)) / 2);
    this.carac.derobee.value = Math.floor(((21 - Misc.toInt(this.carac.taille.value)) + Misc.toInt(this.carac.agilite.value)) / 2);

    this.sante.vie.max = Math.ceil((actor.getTaille() + actor.getConstitution()) / 2);
    this.sante.vie.value = Math.min(this.sante.vie.value, this.sante.vie.max);
    this.attributs.encombrement.value = actor.getEncombrementMax();

    this.attributs.plusdom.value = actor.getBonusDegat();
    this.sante.endurance.max = actor.getEnduranceMax();
    this.sante.endurance.value = Math.min(this.sante.endurance.value, this.sante.endurance.max);

    this.attributs.sconst.value = RdDCarac.calculSConst(actor.getConstitution());
    this.attributs.sust.value = RdDCarac.getCaracDerivee(actor.getTaille()).sust;
    this.sante.fatigue.max = actor.getFatigueMax();
    this.sante.fatigue.value = Math.min(this.sante.fatigue.value, this.sante.fatigue.max);
    this.reve.reve.max = 3 * actor.getReve();
    this.compteurs.chance.max = actor.getChance();
    this.attributs.hautrevant.value = actor.itemTypes[ITEM_TYPES.tete]?.find(it => RdDItemTete.isDonDeHautReve(it))
      ? "Haut rêvant"
      : "";
  }
}
