import { assert } from "../../../core/assert.js";
import { BehaviorStatus } from "./BehaviorStatus.js";
import { CompositeBehavior } from "./composite/CompositeBehavior.js";

/**
 * Will try every child behaviour in order until one succeeds or if all fail - the selector behavior will fail too
 * @author Alex Goldring
 * @copyright Company Named Limited (c) 2026
 */
export class SelectorBehavior extends CompositeBehavior {
    constructor() {
        super();

        /**
         *
         * @type {Behavior}
         * @private
         */
        this.__currentBehaviour = null;

        /**
         *
         * @type {number}
         * @private
         */
        this.__currentBehaviourIndex = -1;
    }

    /**
     *
     * @param {Behavior[]} children
     * @returns {SelectorBehavior}
     */
    static from(children) {
        assert.isArray(children, 'children');

        const r = new SelectorBehavior();

        children.forEach(r.addChild, r);

        return r;
    }

    tick(timeDelta) {
        if (this.__children.length < 1) {
            // no options, nothing chosen
            return BehaviorStatus.Failed;
        }

        //keep going until a child behavior says it's running
        for (; ;) {
            const s = this.__currentBehaviour.tick(timeDelta);

            //if child succeeds or keeps running, do the same
            if (s !== BehaviorStatus.Failed) {
                return s;
            }

            this.__currentBehaviour.finalize();

            //Continue search for a fallback until the last child
            const children = this.__children;

            this.__currentBehaviourIndex++;

            if (this.__currentBehaviourIndex >= children.length) {
                this.__currentBehaviour = null;

                return BehaviorStatus.Failed;
            }

            this.__currentBehaviour = children[this.__currentBehaviourIndex];

            this.__currentBehaviour.initialize(this.context);
        }
    }

    finalize() {
        if (this.__currentBehaviour !== null) {
            this.__currentBehaviour.finalize();
            this.__currentBehaviour = null;
        }

        super.finalize();
    }

    initialize(context) {

        const children = this.__children;

        if (children.length > 0) {

            this.__currentBehaviourIndex = 0;
            this.__currentBehaviour = children[0];

            this.__currentBehaviour.initialize(context);

        } else {
            // no children

            this.__currentBehaviourIndex = -1;
            this.__currentBehaviour = null;

        }

        super.initialize(context);
    }
}
