import { Component } from "../core/world";
import { action, component, variable } from "../utils/decorators";

interface StatState {
    base: number;
    modifierSums: { value: number; max: number; min: number };
    max?: number;
    min?: number;
}

@component
export class Stat<T = {}> extends Component<StatState & T> {
    constructor(args: Omit<StatState, 'modifierSums' | 'base'> & T & { value: number }) {
        super({
            base: args.value,
            modifierSums: { value: 0, max: 0, min: 0 },
            ...args,
        });
    }

    @variable('.') get value(): number {
        const effMin = this.min;
        const effMax = this.max;
        let v = this.state.base + this.state.modifierSums.value;
        if (effMin != null) v = Math.max(effMin, v);
        if (effMax != null) v = Math.min(v, effMax);
        return v;
    }

    @variable get base(): number { return this.state.base; }
    @variable get max(): number | undefined {
        return this.state.max != null ? this.state.max + this.state.modifierSums.max : undefined;
    }
    @variable get min(): number | undefined {
        return this.state.min != null ? this.state.min + this.state.modifierSums.min : undefined;
    }

    @action
    update(amount: number) {
        this.set(this.state.base + amount);
    }

    @action
    set(value: number) {
        const prev = this.value;
        this.state.base = value;
        const next = this.value;
        if (prev !== next) {
            this.emit('set', { prev, value: next });
        }
    }

    applyModifier(delta: number, field: 'value' | 'max' | 'min' = 'value'): void {
        const prev = this.value;
        this.state.modifierSums[field] += delta;
        const next = this.value;
        if (prev !== next) this.emit('set', { prev, value: next });
    }

    removeModifier(delta: number, field: 'value' | 'max' | 'min' = 'value'): void {
        this.applyModifier(-delta, field);
    }

    get current(): number { return this.value; }
}

@component
export class Health extends Stat {
    @action
    kill() {
        this.set(0);
        this.emit('killed');
    }

    @action
    override update(amount: number) {
        if (this.value > 0) {
            super.update(amount);
            if (this.value <= 0) {
                this.kill();
            }
        }
    }
}

