"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var BehaviorManager_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BehaviorManager = void 0;
const cc_1 = require("cc");
const node_1 = require("../node");
const BehaviorTree_1 = require("./BehaviorTree");
const utils_1 = require("./utils");
const { ccclass } = cc_1._decorator;
/***
 * 该组件会自动添加到场景上，用来驱动、管理场景中所有行为树
 */
let BehaviorManager = BehaviorManager_1 = class BehaviorManager extends cc_1.Component {
    constructor() {
        super(...arguments);
        this.behaviorTrees = [];
        // behavior是用户使用的组件，BehaviorTree是真正的行为树数据结构
        this.behaviorTreesMap = new Map();
        // 存储被暂停运行的行为树
        this.pausedBehaviorTreesMap = new Map();
    }
    restart(behaviorTree) {
        if (behaviorTree.behavior.logNodeChange) {
            console.log("restart", behaviorTree);
        }
        // 所有节点都popNode出去以后，未删除的条件重评估的compositeIndex都为-1
        this.removeChildConditionalReevaluate(behaviorTree, -1);
        this.pushNode(behaviorTree, 0, 0);
    }
    // 防止用户手动创建实例但没有设置instance
    onLoad() {
        BehaviorManager_1.instance = this;
    }
    onDestroy() {
        for (const behaviorTree of this.behaviorTrees) {
            this.disableBehavior(behaviorTree.behavior);
        }
    }
    /***
     * 不传isPause的话，默认删掉行为树
     */
    disableBehavior(behavior, isPause = false) {
        const behaviorTree = this.behaviorTreesMap.get(behavior);
        if (!behaviorTree) {
            return;
        }
        if (isPause) {
            // 存进暂停map里
            this.pausedBehaviorTreesMap.set(behavior, behaviorTree);
            behaviorTree.behavior.status = node_1.NodeStatus.Inactive; //设置为未激活状态
        }
        else {
            // 如果是手动disabled的话，让剩下的节点popNode，并不断迭代这个状态作为最终行为树的状态
            let status = node_1.NodeStatus.Success;
            for (let i = behaviorTree.activeStack.length - 1; i >= 0; i--) {
                const curStack = behaviorTree.activeStack[i];
                for (let j = curStack.length - 1; j >= 0; j--) {
                    status = this.popNode(behaviorTree, curStack[curStack.length - 1], i, status, false);
                }
            }
            behavior.status = status;
            this.removeChildConditionalReevaluate(behaviorTree, -1);
            behavior.emit(BehaviorTree_1.BehaviorTreeEvent.BehaviorTreeEnd);
            this.behaviorTreesMap.delete(behavior);
        }
        const index = this.behaviorTrees.findIndex((tree) => tree === behaviorTree);
        // 数组删除该树
        index > -1 && this.behaviorTrees.splice(index, 1);
    }
    enableBehavior(behavior) {
        const rootNode = behavior.behaviorSource.rootNode;
        if (!rootNode) {
            if (behavior.logNodeChange) {
                console.warn("该行为树没有根节点");
            }
            return;
        }
        // 仅被暂停的树，从map里拿出来继续运行
        if (this.pausedBehaviorTreesMap.has(behavior)) {
            const behaviorTree = this.pausedBehaviorTreesMap.get(behavior);
            this.pausedBehaviorTreesMap.delete(behavior);
            this.behaviorTrees.push(behaviorTree);
            this.behaviorTreesMap.set(behavior, behaviorTree);
            return;
        }
        // 全新的树
        const behaviorTree = new BehaviorTree();
        behaviorTree.behavior = behavior;
        this.behaviorTrees.push(behaviorTree);
        this.behaviorTreesMap.set(behavior, behaviorTree);
        //填充数据结构
        behaviorTree.activeStack.push([]);
        behaviorTree.parentIndex.push(-1);
        behaviorTree.relativeChildIndex.push(-1);
        behaviorTree.parentCompositeIndex.push(-1);
        this.addToNodeList(behaviorTree, rootNode, { parentCompositeIndex: -1 });
        //根节点放入运行栈
        behaviorTree.behavior.emit(BehaviorTree_1.BehaviorTreeEvent.BehaviorTreeStart);
        behaviorTree.behavior.status = node_1.NodeStatus.Running;
        //根节点放入运行栈
        this.pushNode(behaviorTree, 0, 0);
    }
    // 数据结构填充
    addToNodeList(behaviorTree, node, data) {
        behaviorTree.nodeList.push(node);
        const index = behaviorTree.nodeList.length - 1;
        if (node instanceof node_1.ParentNode) {
            behaviorTree.childrenIndex.push([]);
            behaviorTree.childConditionalIndex.push([]);
            for (let i = 0; i < node.children.length; i++) {
                behaviorTree.parentIndex.push(index);
                behaviorTree.relativeChildIndex.push(i);
                behaviorTree.childrenIndex[index].push(behaviorTree.nodeList.length);
                if (node instanceof node_1.Composite) {
                    data.parentCompositeIndex = index;
                }
                behaviorTree.parentCompositeIndex.push(data.parentCompositeIndex);
                this.addToNodeList(behaviorTree, node.children[i], data);
            }
        }
        else {
            behaviorTree.childrenIndex.push(null);
            behaviorTree.childConditionalIndex.push(null);
            if (node instanceof node_1.Condition) {
                const parentCompositeIndex = behaviorTree.parentCompositeIndex[index];
                if (parentCompositeIndex !== -1) {
                    behaviorTree.childConditionalIndex[parentCompositeIndex].push(index);
                }
            }
        }
    }
    update() {
        this.tick();
    }
    /***
     * 驱动所有行为树
     */
    tick() {
        //遍历所有树
        for (const behaviorTree of this.behaviorTrees) {
            if (behaviorTree.behavior.logNodeChange) {
                console.log("tick", behaviorTree);
            }
            // 重评估条件
            this.reevaluateConditionalNode(behaviorTree);
            //遍历所有运行栈
            //
            for (let i = behaviorTree.activeStack.length - 1; i >= 0; i--) {
                const curStack = behaviorTree.activeStack[i];
                let prevIndex = -1;
                let prevStatus = node_1.NodeStatus.Inactive;
                while (prevStatus !== node_1.NodeStatus.Running && i < behaviorTree.activeStack.length && curStack.length) {
                    const curIndex = curStack[curStack.length - 1];
                    // 记录前后两次，防止repeater子节点状态为success时，在一个tick里重复运行
                    if (curIndex === prevIndex) {
                        break;
                    }
                    prevIndex = curIndex;
                    // runNode需要传入prevStatus的原因是
                    // 例如selector一个子节点是running状态，某个tick变成了success状态，子节点popNode出去
                    // 下一个tick进来，栈顶元素是selector，此时canExecute为false，runParentNode没办法返回一个具体的状态
                    // 此时就可以把上一个tick子节点的状态作为本次tick的selector的状态（反转节点同理）
                    prevStatus = this.runNode(behaviorTree, curIndex, i, prevStatus);
                }
            }
        }
    }
    runNode(behaviorTree, index, stackIndex, prevStatus) {
        const node = behaviorTree.nodeList[index];
        // 保证运行的节点在栈顶
        this.pushNode(behaviorTree, index, stackIndex);
        let status = prevStatus;
        if (node instanceof node_1.ParentNode) {
            status = this.runParentNode(behaviorTree, index, stackIndex, status);
            // 并行节点的状态不由某个子节点状态决定，而是由多个共同决定，所以重新计算status
            status = node.overrideStatus(status);
        }
        else {
            // 执行目标事件
            const res1 = node.onUpdate();
            const [done, res2] = this.emitEvent(behaviorTree, node.data, "onUpdate");
            status = done ? res2 : res1;
        }
        // 非running的节点pop出去
        if (status !== node_1.NodeStatus.Running) {
            status = this.popNode(behaviorTree, index, stackIndex, status);
        }
        return status;
    }
    runParentNode(behaviorTree, index, stackIndex, status) {
        const node = behaviorTree.nodeList[index];
        //防止running状态的并行节点重复运行
        if (node.canRunParallelChildren() && node.overrideStatus(node_1.NodeStatus.Running) === node_1.NodeStatus.Running) {
            return status;
        }
        let childStatus = node_1.NodeStatus.Inactive;
        let preIndex = -1;
        //并行节点可以存在多个running状态的子节点
        while (node.canExecute() && (childStatus !== node_1.NodeStatus.Running || node.canRunParallelChildren())) {
            const childIndex = node.index;
            // 并行节点创建新的运行栈
            if (node.canRunParallelChildren()) {
                behaviorTree.activeStack.push([]);
                stackIndex = behaviorTree.activeStack.length - 1;
                node.onChildStarted();
            }
            let curIndex = childIndex;
            // 防止repeater或untilSuccess等可以重复运行的节点，canExecute一直是true，会导致一直进入while
            // 所以加入curIndex和preIndex，保证不能在一次runParentNode里重复运行相同节点
            if (curIndex === preIndex) {
                status = node_1.NodeStatus.Running;
                break;
            }
            preIndex = curIndex;
            status = childStatus = this.runNode(behaviorTree, behaviorTree.childrenIndex[index][childIndex], stackIndex, status);
        }
        // 子节点有运行就返回子节点的状态，没有就返回上一次运行的状态
        return status;
    }
    pushNode(behaviorTree, index, stackIndex) {
        const stack = behaviorTree.activeStack[stackIndex];
        // 防止重复推入
        if (stack.length === 0 || stack[stack.length - 1] !== index) {
            stack.push(index);
            const node = behaviorTree.nodeList[index];
            if (behaviorTree.behavior.logNodeChange) {
                console.log("pushNode", node, "index:", index, "stackIndex:", stackIndex);
            }
            node.onStart();
            this.emitEvent(behaviorTree, node.data, "onStart");
        }
    }
    popNode(behaviorTree, index, stackIndex, status, popChildren = true) {
        const curStack = behaviorTree.activeStack[stackIndex];
        curStack.pop();
        const node = behaviorTree.nodeList[index];
        node.onEnd();
        this.emitEvent(behaviorTree, node.data, "onEnd");
        if (behaviorTree.behavior.logNodeChange) {
            console.log("popNode", node, "index:", index, "stackIndex:", stackIndex, "status:", status);
        }
        const parentIndex = behaviorTree.parentIndex[index];
        if (parentIndex !== -1) {
            if (node instanceof node_1.Condition) {
                const parentCompositeIndex = behaviorTree.parentCompositeIndex[index];
                if (parentCompositeIndex !== -1) {
                    const composite = behaviorTree.nodeList[parentCompositeIndex];
                    //自己是条件节点并且父级的中断类型存在，创建重判断实例
                    if (composite.abortType !== node_1.AbortType.None) {
                        // 父composite为LowerPriority时，条件重评估不希望此时执行，而是父composite popNode出去再执行
                        const compositeIndex = composite.abortType === node_1.AbortType.LowerPriority ? -1 : parentCompositeIndex;
                        // 防止该条件存在条件重评估对象
                        if (behaviorTree.conditionalReevaluateMap.has(index)) {
                            const conditionalReevaluate = behaviorTree.conditionalReevaluateMap.get(index);
                            conditionalReevaluate.compositeIndex = compositeIndex;
                            conditionalReevaluate.status = status;
                        }
                        else {
                            const conditionalReevaluate = new ConditionalReevaluate(index, stackIndex, status, compositeIndex);
                            if (behaviorTree.behavior.logNodeChange) {
                                console.log("new ConditionalReevaluate", conditionalReevaluate, "index:", index, "stackIndex:", stackIndex, "compositeIndex", compositeIndex);
                            }
                            behaviorTree.conditionalReevaluate.push(conditionalReevaluate);
                            behaviorTree.conditionalReevaluateMap.set(index, conditionalReevaluate);
                        }
                    }
                }
            }
            const parentNode = behaviorTree.nodeList[parentIndex];
            parentNode.onChildExecuted(status, behaviorTree.relativeChildIndex[index]);
            // 父节点是反转节点，修改结果
            if (parentNode instanceof node_1.Decorator) {
                status = parentNode.decorate(status);
            }
        }
        if (node instanceof node_1.Composite) {
            // 类型是Self或者None时，清空所有子条件重评估，或者popNode的节点是当前运行栈的最后一项，删除该节点管理的条件重评估
            if ([node_1.AbortType.Self, node_1.AbortType.None].includes(node.abortType) || !curStack.length) {
                this.removeChildConditionalReevaluate(behaviorTree, index);
                // 类型是LowerPriority或者Both，上移compositeIndex，compositeIndex为-1的条件重评估对象，LowerPriority，会因此激活
            }
            else if ([node_1.AbortType.LowerPriority, node_1.AbortType.Both].includes(node.abortType)) {
                for (let i = 0; i < behaviorTree.childConditionalIndex[index].length; i++) {
                    const childConditionalIndex = behaviorTree.childConditionalIndex[index][i];
                    if (behaviorTree.conditionalReevaluateMap.has(childConditionalIndex)) {
                        const conditionalReevaluate = behaviorTree.conditionalReevaluateMap.get(childConditionalIndex);
                        conditionalReevaluate.compositeIndex = behaviorTree.parentCompositeIndex[index];
                    }
                }
                // 上移当前被移除的composite管理的所有条件重评估的compositeIndex
                for (let i = 0; i < behaviorTree.conditionalReevaluate.length; i++) {
                    const conditionalReevaluate = behaviorTree.conditionalReevaluate[i];
                    if (conditionalReevaluate.compositeIndex === index) {
                        conditionalReevaluate.compositeIndex = behaviorTree.parentCompositeIndex[index];
                    }
                }
            }
        }
        if (popChildren) {
            //并行节点删除其他正在运行的子节点
            for (let i = behaviorTree.activeStack.length - 1; i > stackIndex; i--) {
                const stack = behaviorTree.activeStack[i];
                if (stack.length > 0 && this.isParentNode(behaviorTree, index, stack[stack.length - 1])) {
                    let status = node_1.NodeStatus.Failure;
                    for (let j = stack.length - 1; j >= 0; j--) {
                        status = this.popNode(behaviorTree, stack[stack.length - 1], i, status, false);
                    }
                }
            }
        }
        // 当前运行栈没有节点了
        if (curStack.length === 0) {
            // 当前运行栈就是主运行栈
            if (stackIndex === 0) {
                // 重启行为树
                if (behaviorTree.behavior.restartWhenComplete) {
                    this.restart(behaviorTree);
                }
                else {
                    this.disableBehavior(behaviorTree.behavior);
                    //修改disableBehavior写入的status
                    behaviorTree.behavior.status = status;
                }
                status = node_1.NodeStatus.Inactive;
            }
            else {
                // 删除其他空子运行栈
                behaviorTree.activeStack.splice(stackIndex, 1);
                // 返回running，退出tick的while循环
                status = node_1.NodeStatus.Running;
            }
        }
        return status;
    }
    reevaluateConditionalNode(behaviorTree) {
        if (behaviorTree.behavior.logNodeChange) {
            console.log("reevaluateConditionalNode start", behaviorTree.conditionalReevaluate);
        }
        for (let i = behaviorTree.conditionalReevaluate.length - 1; i >= 0; i--) {
            const { index, compositeIndex, status: prevStatus } = behaviorTree.conditionalReevaluate[i];
            //父组合节点索引不存在或者故意设置为-1，不进行评估
            if (compositeIndex === -1) {
                continue;
            }
            const node = behaviorTree.nodeList[index];
            let status = node_1.NodeStatus.Inactive;
            const res1 = node.onUpdate();
            const [done, res2] = this.emitEvent(behaviorTree, node.data, "onUpdate");
            status = done ? res2 : res1;
            //条件一致
            if (status === prevStatus) {
                continue;
            }
            if (behaviorTree.behavior.logNodeChange) {
                console.log("reevaluateConditionalNode success", behaviorTree.conditionalReevaluate[i]);
            }
            for (let j = behaviorTree.activeStack.length - 1; j >= 0; j--) {
                const stack = behaviorTree.activeStack[j];
                if (!stack.length) {
                    continue;
                }
                //当前节点及他到公共父节点之间所有父节点pop出去
                let curNodeIndex = stack[stack.length - 1];
                const commonParentIndex = this.findCommonParentIndex(behaviorTree, curNodeIndex, index);
                // 该条件重评估的compositeIndex是commonParent的父级
                if (this.isParentNode(behaviorTree, compositeIndex, commonParentIndex)) {
                    // popNode可能会修改activeStack，保存一下长度，相同才执行
                    const stackLen = behaviorTree.activeStack.length;
                    while (curNodeIndex !== -1 &&
                        curNodeIndex !== commonParentIndex &&
                        behaviorTree.activeStack.length === stackLen) {
                        this.popNode(behaviorTree, curNodeIndex, j, node_1.NodeStatus.Failure, false);
                        curNodeIndex = behaviorTree.parentIndex[curNodeIndex];
                    }
                }
            }
            //右边的包括自己的重评估条件删除掉
            for (let j = behaviorTree.conditionalReevaluate.length - 1; j >= i; j--) {
                const conditionalReevaluate = behaviorTree.conditionalReevaluate[j];
                if (this.isParentNode(behaviorTree, compositeIndex, conditionalReevaluate.index)) {
                    behaviorTree.conditionalReevaluateMap.delete(conditionalReevaluate.index);
                    behaviorTree.conditionalReevaluate.splice(j, 1);
                }
            }
            const compositeNode = behaviorTree.nodeList[behaviorTree.parentCompositeIndex[index]];
            // 遍历左侧的条件重评估对象
            for (let j = i - 1; j >= 0; j--) {
                const conditionalReevaluate = behaviorTree.conditionalReevaluate[j];
                if (behaviorTree.parentCompositeIndex[conditionalReevaluate.index] === behaviorTree.parentCompositeIndex[index]) {
                    // composite节点是LowerPriority，则让这些条件停止运行
                    if (compositeNode.abortType === node_1.AbortType.LowerPriority) {
                        conditionalReevaluate.compositeIndex = -1;
                        // composite节点是Both或者Self，条件重评估的compositeIndex等于parentCompositeIndex
                    }
                    else if ([node_1.AbortType.Both, node_1.AbortType.Self].includes(compositeNode.abortType)) {
                        conditionalReevaluate.index = behaviorTree.parentCompositeIndex[index];
                    }
                }
            }
            //当前条件节点到CommonParentNode之间所有Composite节点执行onConditionalAbort
            const conditionalParentIndex = [];
            for (let m = behaviorTree.parentIndex[index]; m != compositeIndex; m = behaviorTree.parentIndex[m]) {
                conditionalParentIndex.push(m);
            }
            conditionalParentIndex.push(compositeIndex);
            //从顶部到底部的顺序执行
            for (let n = conditionalParentIndex.length - 1; n >= 0; n--) {
                const parentTask = behaviorTree.nodeList[conditionalParentIndex[n]];
                if (n === 0) {
                    parentTask.onConditionalAbort(behaviorTree.relativeChildIndex[index]);
                }
                else {
                    parentTask.onConditionalAbort(behaviorTree.relativeChildIndex[conditionalParentIndex[n - 1]]);
                }
            }
        }
    }
    removeChildConditionalReevaluate(behaviorTree, compositeIndex) {
        for (let i = behaviorTree.conditionalReevaluate.length - 1; i >= 0; i--) {
            if (behaviorTree.conditionalReevaluate[i].compositeIndex === compositeIndex) {
                behaviorTree.conditionalReevaluateMap.delete(behaviorTree.conditionalReevaluate[i].index);
                behaviorTree.conditionalReevaluate.splice(i, 1);
            }
        }
    }
    findCommonParentIndex(behaviorTree, index1, index2) {
        const set = new Set();
        let num = index1;
        while (num !== -1) {
            set.add(num);
            num = behaviorTree.parentIndex[num];
        }
        num = index2;
        while (!set.has(num)) {
            num = behaviorTree.parentIndex[num];
        }
        return num;
    }
    isParentNode(behaviorTree, possibleParent, possibleChild) {
        for (let num = possibleChild; num !== -1; num = behaviorTree.parentIndex[num]) {
            if (num === possibleParent) {
                return true;
            }
        }
        return false;
    }
    /***
     * 执行节点事件
     */
    emitEvent(behaviorTree, nodeData, lifeCycle) {
        const dump = nodeData.event[lifeCycle];
        const nodeUuid = dump.node;
        const compUuid = dump.comp;
        const methodName = dump.method;
        const methodData = dump.data;
        if (!nodeUuid || !compUuid || !methodName) {
            return [false, null];
        }
        // 行为树组件所在cocos节点
        const curNode = behaviorTree.behavior.node;
        // 先从当前节点开始层序遍历
        let target = (0, utils_1.bfsCcNode)(curNode, nodeUuid);
        // 找不到再从scene节点开始层序遍历
        if (!target) {
            target = (0, utils_1.bfsCcNode)(cc_1.director.getScene(), nodeUuid, curNode.uuid);
        }
        if (!target) {
            return [false, null];
        }
        const comp = target._components.find((comp) => comp.uuid === compUuid);
        if (!comp) {
            return [false, null];
        }
        const method = comp[methodName];
        if (!method) {
            return [false, null];
        }
        const res = method.call(comp, methodData);
        // 用户忘记写返回值，一律返回失败
        const result = res !== undefined ? res : node_1.NodeStatus.Failure;
        return [true, result];
    }
};
BehaviorManager.instance = null;
BehaviorManager = BehaviorManager_1 = __decorate([
    ccclass("BehaviorManager")
], BehaviorManager);
exports.BehaviorManager = BehaviorManager;
/***
 * 行为树数据结构，具体执行逻辑由BehaviorManager驱动
 */
class BehaviorTree {
    constructor() {
        this.activeStack = [];
        this.nodeList = [];
        //当前节点的父节点
        this.parentIndex = [];
        //当前节点的子节点
        this.childrenIndex = [];
        /***
         * 为了实现中断
         */
        //当前节点是父节点的第几个子节点
        this.relativeChildIndex = [];
        //当前节点的父组合节点
        this.parentCompositeIndex = [];
        //当前节点的子条件节点
        this.childConditionalIndex = [];
        //所有条件重评估
        this.conditionalReevaluate = [];
        //条件重评估id的map
        this.conditionalReevaluateMap = new Map();
    }
}
/***
 * 条件重评估数据结构
 * 各种情况讲解：
 * 1、LowerPriority：左侧的重评估条件可以打断右侧Action节点的运行，不过不是所有都能打断，当Action属于该compositeIndex所管理的子树才能打断
 *  因此，随着compositeIndex逐渐上移，该条件能打断的范围就会越大，当然这就需要此条件的父节点均有LowerPriority或者Both，才能让compositeIndex一直上移
 * 2、Self：只能打断跟自己同一Composite节点下的其他节点的运行，当该Composite被popNode时，条件也会被删除
 * 3、Parallel：Parallel下有多个分支都有LowerPriority的条件重评估对象：
 *    情况1、假设某个分支返回Running状态，此时这个分支下的compositeIndex未达到并行节点，无法管理其他分支下Action运行
 *    情况2：返回Success或者Failure状态，当该运行栈最后一个元素popNode出去时，此时栈为空，会删除其管理的条件重评估
 *          如果该条件的compositeIndex是-1，不会进入compositeIndex上移逻辑，因此也无法运行
 *    总结：某个并行节点下的多个并行分支，各自的条件不会干扰
 */
class ConditionalReevaluate {
    constructor(index, stackIndex, status, compositeIndex) {
        this.index = index;
        this.stackIndex = stackIndex;
        this.status = status;
        this.compositeIndex = compositeIndex;
    }
}
