
import { Node, Vec3 } from "cc";
import { Timer } from "../../../../../../extensions/oops-plugin-framework/assets/core/common/timer/Timer";
import { Vec3Util } from "../../../../../../extensions/oops-plugin-framework/assets/core/utils/Vec3Util";
import { ecs } from "../../../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";

/** 向目标移动，移动过程中目标位置变化会自动修正移动目标点，直到未修正前移动到目标点停止 */
@ecs.register('MoveTo')
export class MoveToComp extends ecs.Comp {
    /** 移动节点 */
    node: Node = null!;
    /** 移动方向 */
    velocity: Vec3 = Vec3Util.zero;
    /** 移动速度（每秒移动的像素距离） */
    speed: number = 0;
    /** 目标实体ECS编号、目标位置 */
    target: Vec3 | Node | null = null;

    /** 坐标标（默认本地坐标） */
    ns: number = Node.NodeSpace.LOCAL;
    /** 偏移距离 */
    offset: number = 0;
    /** 偏移向量 */
    offsetVector: Vec3 | null = null;
    /** 移动完成回调 */
    onComplete: Function | null = null;
    /** 距离变化时 */
    onChange: Function | null = null;

    reset() {
        this.ns = Node.NodeSpace.LOCAL;
        this.offset = 0;
        this.target = null;
        this.offsetVector = null;
        this.onComplete = null;
        this.onChange = null;
    }
}

@ecs.register('VariableMoveTo')
class VariableMoveToComponent extends ecs.Comp {
    /** 延时触发器 */
    timer: Timer = new Timer();
    /** 终点备份 */
    end: Vec3 | null = null;
    /** 目标位置 */
    target!: Vec3;

    reset() {
        this.end = null;
        this.timer.reset();
    }
}

/** 跟踪移动到目标位置 */
export class MoveToSystem extends ecs.ComblockSystem<ecs.Entity> implements ecs.IEntityEnterSystem, ecs.IEntityRemoveSystem, ecs.ISystemUpdate {
    filter(): ecs.IMatcher {
        return ecs.allOf(MoveToComp);
    }

    entityEnter(e: ecs.Entity): void {
        e.add(VariableMoveToComponent);
    }

    entityRemove(e: ecs.Entity): void {
        e.remove(VariableMoveToComponent);
    }

    update(e: ecs.Entity) {
        let move = e.get(MoveToComp);
        let mtv = e.get(VariableMoveToComponent);
        let end: Vec3;

        // console.assert(move.speed > 0, "移动速度必须要大于零");

        if (move.target instanceof Node) {
            end = move.ns == Node.NodeSpace.WORLD ? move.target.worldPosition : move.target.position;
        }
        else {
            end = move.target as Vec3;
        }

        // 目标移动后，重计算移动方向与移动到目标点的速度
        if (mtv.end == null || !mtv.end.strictEquals(end)) {
            let target = end.clone();
            if (move.offsetVector) {
                target = target.add(move.offsetVector);           // 这里的问题
            }

            // 移动方向与移动数度
            let start = move.ns == Node.NodeSpace.WORLD ? move.node.worldPosition : move.node.position;
            move.velocity = Vec3Util.sub(target, start).normalize();

            // 移动时间与目标偏位置计算
            let distance = Vec3.distance(start, target) - move.offset;

            move.onChange?.call(this);

            if (distance - move.offset <= 0) {
                this.exit(e);
            }
            else {
                mtv.timer.step = distance / move.speed;
                mtv.end = end.clone();
                mtv.target = move.velocity.clone().multiplyScalar(distance).add(start);
            }
        }

        if (move.speed > 0) {
            let trans = Vec3Util.mul(move.velocity, move.speed * this.dt);

            let start = move.ns == Node.NodeSpace.WORLD ? move.node.worldPosition : move.node.position;
            let distance = Vec3.distance(start, mtv.target) - move.offset;
            if (trans.length() > distance || mtv.timer.update(this.dt)) {
                if (move.ns == Node.NodeSpace.WORLD)
                    move.node.worldPosition = mtv.target;
                else
                    move.node.position = mtv.target;
                this.exit(e);
            } else {
                move.node.translate(trans, move.ns);
            }
        }
    }

    private exit(e: ecs.Entity) {
        let move = e.get(MoveToComp);
        move.onComplete?.call(this);
        e.remove(VariableMoveToComponent);
        e.remove(MoveToComp);
    }
}