Source: widgets/constraint.js

const Vector = require("../tools/vector");
const DynObject = require("../dynObject");

// Try to import matter-js as a commonJS module

var Matter;

if(typeof window === "object") {
	Matter = window.Matter;
}

else {
	Matter = require("matter-js");
}

/**
 * 
 * 
 * Constraint Widget
 * 
 * @function
 * @memberof PhSim.Widgets
 * @param {PhSim} phsim 
 * @param {Object} widget - Widget Options
 * @param {LOAddress|PhSim.DynObject} [widget.objectA] - Object A - First point.
 * @param {LOAddress|PhSim.DynObject} [widget.objectB] - Object B - Second Point
 * @param {Vector} [widget.pointA] - First point (see `widget.position` for more information)
 * @param {Vector} [widget.pointB] - Second point (see `widget.position` for more information)
 * @param {"relative"|"absolute"} [widget.position = "absolute"] - Positions of points. 
 * 
 * If set to `"relative"`, then the rules for positioning a point is the following:
 * 
 * * If `widget.objectA` is set, then `widget.pointA` defines the offset from the 
 * centroid of `widget.objectA`. Otherwise, the point is set to a point in the phsim space.
 * 
 * * If `widget.objectB` is set, then `widget.pointB` defines the offset from the centroid
 * of `widget.objectB`. Otherwise, the point is set to a point in the phsim space.
 * 
 * Note: If one is familar with Matter.js, then the rules are simular to rules of making a 
 * constraint are simular to those in Matter.js.
 * 
 * If set to `"absolute"`, then the rules for positioning a point is that the points 
 * are set to points in space. This is the default value.
 */

function constraint(phsim,widget) {

    var position = "absolute";

    if(widget.position === "relative") {
        position = "relative"
    } 
    
    else if(widget.position === "absolute") {
        position = "absolute";
    }
    
    var b = {}

    if(position === "absolute") {

        if(widget.objectA) {

            if(widget.objectA instanceof DynObject) {
                b.bodyA = widget.objectA.matter;
            }
    
            else {
    
                if(typeof widget.objectA.L === "number" && typeof widget.objectA.O === "number") {
                    b.bodyA = phsim.LO(widget.objectA.L,widget.objectA.O).matter;
                }
    
                else {
                    b.bodyA = phsim.optionMap.get(widget.objectA).matter;
                }
    
            }
    
        }
    
        if(widget.objectB) {
            b.bodyB = phsim.LO(widget.objectB.L,widget.objectB.O).matter;
    
            if(widget.objectB instanceof DynObject) {
                b.bodyB = widget.objectB.matter;
            }
    
            else {
    
                if(typeof widget.objectB.L === "number" && typeof widget.objectB.O === "number") {
                    b.bodyB = phsim.LO(widget.objectB.L,widget.objectB.O).matter;
                }
    
                else {
                    b.bodyB = phsim.optionMap.get(widget.objectB).matter;
                }
    
            }
    
        }
    
        if(widget.pointA) {
    
            if(widget.objectA) {
                b.pointA = Vector.subtract(widget.pointA,b.bodyA.position);
            }
    
            else {
                b.pointA = widget.pointA;
            }
    
        }
    
        if(widget.pointB) {
            
            if(widget.objectB) {
                b.pointB = Vector.subtract(widget.pointB,b.bodyB.position);
            }
    
            else {
                b.pointB = widget.pointB;
            }
        }

    }

    if(position === "relative") {
        b.pointA = widget.pointA;
        b.pointB = widget.pointB;
        b.bodyA = widget.objectA.plugin.dynObject;
        b.bodyB = widget.objectB.plugin.dynObject;
    }

    var c = Matter.Constraint.create(b);

    Matter.World.add(phsim.matterJSWorld,c);

}

module.exports = constraint;