import { serializable } from "../../engine/engine_serialization_decorator.js";
import { Behaviour } from "../Component.js";
import { Rigidbody } from "../RigidBody.js";


/**
 * Used to attract Rigidbodies towards the position of this component.
 * Add Rigidbodies to the `targets` array to have them be attracted.  
 * You can use negative strength values to create a repulsion effect.
 * 
 * @example Attractor component attracting a Rigidbody
 * ```ts
 * const attractor = object.addComponent(Attractor);
 * attractor.strength = 5; // positive value to attract
 * attractor.radius = 10; // only attract within 10 units
 * attractor.targets.push(rigidbody); // add the Rigidbody to be attracted
 * @summary Attract Rigidbodies towards the position of this component
 * @category Physics
 * @group Components
 */
export class Attractor extends Behaviour {

    @serializable()
    strength: number = 1;

    @serializable()
    radius: number = 2;

    @serializable(Rigidbody)
    targets: Rigidbody[] = [];

    update() {
        const wp = this.gameObject.worldPosition;
        const factor = -this.strength * this.context.time.deltaTime;
        this.targets?.forEach(t => {
            if(!t) return;
            const dir = t.gameObject.worldPosition.sub(wp);
            const length = dir.length();
            if (length > this.radius) return;
            let _factor = factor;
            if (length > 1) _factor /= length * length;
            else _factor /= Math.max(.05, length);
            t.applyImpulse(dir.multiplyScalar(_factor));
        })
    }


}