import BaseItem from "./baseItem.mjs";

const {
    ArrayField, 
    SchemaField, 
    BooleanField, 
    NumberField, 
    StringField, 
    HTMLField
} = foundry.data.fields;

export class AdvantageDataModel extends BaseItem {

    static defineSchema() {
        return {
            name: new StringField({required: true}),
            description: new HTMLField(),
            nachteil: new BooleanField({required: true, initialValue: false}),
            schlechteEigenschaft: new BooleanField({required: true, initialValue: false}),

            // Optional Fields
            value: new StringField({required: false, nullable: true}),
            mod: new ArrayField(new SchemaField({
                name: new StringField(),
                talent: new StringField({required: false}),
                value: new NumberField(),
            }), {required: false}),
            auswahl: new ArrayField(
                new SchemaField({
                    name: new StringField(),
                    requirements: new ArrayField(
                        new SchemaField({
                            attribute: new StringField(),
                            minValue: new NumberField(),
                            maxValue: new NumberField(),
                            sonderfertigkeit: new StringField(),
                            talent: new StringField(),
                            compare: new SchemaField({
                                ownAttribute: new StringField(),
                                targetAttribute: new StringField(),
                                operation: new StringField(),
                            }, {required: false}),
                        })
                    ),
                    mod: new ArrayField(new SchemaField({
                        name: new StringField(),
                        talent: new StringField({required: false}),
                        value: new NumberField(),
                    }))
                }), {required: false}
            ),
        }
        /*

         name: String,             // Name of Vornachteil will be used for rendering and referencing by other Items
         description: HTMLString,  // only used for rendering
         variant: [String]?,       // variant name of Vornachteil e.g. "Mut" in the case of "Herausragende Eigenschaft"
         levels: [Number]?,        // available levels e.g. 1, 2 in the case of "Flink"
         mods: [
            {
                level: Number?,    // in reference to level of the Vornachteil, is null when it does not have any levels or is the only modification
                field: String,     // Reference to Actor Data e.g. "FF" maps to "FF.mod"
                value: Number,     // value of the Modification e.g. "+2" maps to 2
                requirement: {
                    field: String     // Reference to Actor Data e.g. "BE" maps "be.aktuell"
                    operation: String // Supported: "<=", ">"
                    value: Number     // Target Value the referenced field has to compare against
                }?                 // optional when the mod does not have an active requirement
            }
         ]

         */
    }

    #getRequirements() {
        if (this.value && this.auswahl?.find(p => p.name === this.value)) {
            const auswahl = this.auswahl?.find(p => p.name === this.value)
            return auswahl.requirement
        } else {
            return this.requirement
        }
    }

    getActiveMod(options) {
        if (this.isActive(options)) {
            if (this.value && this.auswahl?.find(p => p.name === this.value)) {
                const auswahl = this.auswahl?.find(p => p.name === this.value)
                return auswahl.mod
            } else {
                return this.mod
            }
        } else {
            return []
        }
    }

    isActive(options) {

        const requirements = this.#getRequirements()

        let passes = true
        let mod = 0

        if (this.parent?.actor) {
            const flatActor = foundry.utils.flattenObject(this.parent.actor.system)
            if (requirements) for (let requirement of requirements) {

                let targetField = null

                if (requirement.attribute) {
                    targetField = flatActor?.[requirement.attribute.toLocaleLowerCase()]
                }
                if (requirement.talent) {
                    targetField = this.parent.actor.itemTypes["Skill"].find(p => p.name.toLocaleLowerCase() === requirement.talent.toLocaleLowerCase())?.taw ?? Number.NaN
                }
                if (requirement.minValue) {
                    passes = requirement.minValue <= targetField
                    if (!passes) console.debug(`fails requirement ${requirement.attribute ?? requirement.talent} (${requirement.minValue} <= ${targetField})`)
                }
                if (requirement.maxValue) {
                    passes = targetField <= requirement.maxValue
                    if (!passes) console.debug(`fails requirement ${requirement.attribute ?? requirement.talent} (${targetField} <= ${requirement.maxValue})`)
                }
                if (requirement.sonderfertigkeit) { // FIXME fails when it tries to self reference itself e.g. Ausweichen II has Ausweichen I as requirement
                    const regexp = /(\w*)\W?(\w*)?/
                    const [variantName, baseAbility, level] = regexp.exec(requirement.sonderfertigkeit)

                    passes = this.parent.actor.itemTypes["SpecialAbility"].find(p => p.name === baseAbility) !== undefined
                    if (!passes) console.debug(`fails requirement ${requirement.sonderfertigkeit} (not in possession)`)
                }
                if (requirement["compare"]) {
                    const {ownAttribute, operation, targetAttribute} = requirement["compare"]
                    if (options.target) {
                        const flatTarget = foundry.utils.flattenObject(options.target.system)
                        const foreignTargetField = flatTarget[targetAttribute]
                        const ourTargetField = flatActor[ownAttribute]
                        switch (operation) {
                            case "lt":
                                passes = ourTargetField < foreignTargetField;
                                break;
                            case "lte":
                                passes = ourTargetField <= foreignTargetField;
                                break;
                            case "eq":
                                passes = ourTargetField == foreignTargetField;
                                break;
                            case "neq":
                                passes = ourTargetField != foreignTargetField;
                                break;
                            case "gte":
                                passes = ourTargetField >= foreignTargetField;
                                break;
                            case "gt":
                                passes = ourTargetField > foreignTargetField;
                                break;
                        }
                        if (!passes) {
                            console.debug(`fails compare requirement ${ownAttribute} ${operation} ${targetAttribute}`)
                        }
                    } else {
                        console.debug(`fails compare requirement as no target has been selected`)
                        return false // cant pass as we dont have a target
                    }
                }
                if (!passes) {
                    console.debug("fails atleast 1 requirement of ", this)
                    break
                }
            }
            if (passes) {
                if (options?.weapon) {
                    for (const waff of this.waffenLimit) {
                        if (waff.waffe) {
                            passes = options?.weapon?.name === waff.waffe ?? false
                            if (waff.mod) mod = waff.mod
                            if (passes)
                                break
                        }
                        if (waff.gruppe) {
                            passes = options?.skill?.name === waff.gruppe ?? false
                            if (waff.mod) mod = waff.mod
                            if (passes)
                                break
                        }
                    }
                }
            }


        }
        return {passes, mod}
    }

}
