import { Constraint } from './Constraint'
import { AngleLockEquation } from '../equations/AngleLockEquation'
import { Utils } from '../utils/Utils';

export class GearConstraint extends Constraint {

    /**
     * The gear ratio.
     * @property ratio
     * @type {Number}
     */
    ratio: any;

    /**
     * The relative angle
     * @property angle
     * @type {Number}
     */
    angle: any;
    /**
     * 齿轮约束
     * Constrains the angle of two bodies to each other to be equal. If a gear ratio is not one, the angle of bodyA must be a multiple of the angle of bodyB.
     * @class GearConstraint
     * @constructor
     * @author schteppe
     * @param {Body}            bodyA
     * @param {Body}            bodyB
     * @param {Object}          [options]
     * @param {Number}          [options.angle=0] Relative angle between the bodies. Will be set to the current angle between the bodies (the gear ratio is accounted for).
     * @param {Number}          [options.ratio=1] Gear ratio.
     * @param {Number}          [options.maxTorque] Maximum torque to apply.
     * @extends Constraint
     *
     * @example
     *     var constraint = new GearConstraint(bodyA, bodyB);
     *     world.addConstraint(constraint);
     *
     * @example
     *     var constraint = new GearConstraint(bodyA, bodyB, {
     *         ratio: 2,
     *         maxTorque: 1000
     *     });
     *     world.addConstraint(constraint);
     */
    constructor(bodyA, bodyB, options) {
        options = options || {};

        super(bodyA, bodyB, Constraint.GEAR, options);


        this.ratio = options.ratio !== undefined ? options.ratio : 1;

        this.angle = options.angle !== undefined ? options.angle : bodyB.angle - this.ratio * bodyA.angle;

        // Send same parameters to the equation
        var angleLockOptions: any = Utils.shallowClone(options);
        angleLockOptions.angle = this.angle;
        angleLockOptions.ratio = this.ratio;

        this.equations = [
            new AngleLockEquation(bodyA, bodyB, angleLockOptions),
        ];

        // Set max torque
        if (options.maxTorque !== undefined) {
            this.setMaxTorque(options.maxTorque);
        }
    }



    update() {
        var eq = this.equations[0];
        var ratio = this.ratio;
        if (eq["ratio"] !== ratio) {
            eq["setRatio"](ratio);
        }
        eq["angle"] = this.angle;
    };

    /**
     * Set the max torque for the constraint.
     * @method setMaxTorque
     * @param {Number} torque
     */
    setMaxTorque(torque:number):void {
        this.equations[0]["setMaxTorque"](torque);
    };

    /**
     * Get the max torque for the constraint.
     * @method getMaxTorque
     * @return {Number}
     */
    getMaxTorque():number {
        return this.equations[0].maxForce;
    };
}