package primitives.machines;
import java.awt.*;
import java.awt.event.*;
import primitives.geomtry.*;
/**
*An Adder Linkages is composed by two ScalarMultiplier Linkages; 
*The first preforms the computation: output=(input1+input2)/2.
*The second preforms the computation: output=2*input
*The Adder does not inherit from Machine, instead it manipulates 2 ScalarMultiplier1 objects
*Which are its members.
*@see FunctionalLinkage
*@see ScalarMultiplier1
*@author Dori Eldar
*/
public class Adder implements FunctionalLinkage{
	/**
	*The object preforming the average computation initialized with 2 input joints.
	*@see ScalarMultiplier1
	*/
	ScalarMultiplier1 average;
	/**
	*The object preforming multiplication by 2 initialized with one input joint.
	*/
	ScalarMultiplier1 a2scalar;
	//int r;
	/**
	*Used for storing a backup of the locations of one of the ScalarMultiplier1 members
	*/
	Coordinate[] tempJoints = new Coordinate[6];
	/**
	*@param d the rectangle to draw the Adder in. The 2 ScalarMultipliers are initialized with d
	*@see ScalarMultiplier1#ScalarMultiplier1
	*/
	public Adder(Rectangle d){
		a2scalar = new ScalarMultiplier1(d,2,true);
		average = new ScalarMultiplier1(d,0.5,false);
		average.origin = a2scalar.origin;
		Coordinate[] tinputs = {
		new Coordinate(a2scalar.origin.x+40,a2scalar.origin.y+40),
		new Coordinate(a2scalar.origin.x-20,a2scalar.origin.y+20)};
		forceInputJoints(tinputs);
	}
	/**
	*A copy of the 2 input joints.
	*This is a redondence field since The ScalarMultiplier1 class defines this field too.
	*/
	Coordinate inputs[] = {new Coordinate(),new Coordinate()};
	/**
	*@see FunctionalLinkage#forceInputJoints
	*/
	public Coordinate[] forceInputJoints(Coordinate[] inputs){
		this.inputs[0].move(a2scalar.getInputJoints()[0]);
		this.inputs[1].move(average.forceInputJoints(inputs)[0]);
		return a2scalar.forceInputJoints(this.inputs);
	}
	/**
	*@exception MachineException .
	*@see FunctionalLinkage#setInputJoints
	*/
	public Coordinate[] setInputJoints(Coordinate[] inputJoints) throws MachineException{
		inputs[1].move(average.setInputJoints(inputJoints)[0]);
		return a2scalar.setInputJoints(inputs);
	}
	/**
	*@see FunctionalLinkage#getOutputJoints
	*/
	public Coordinate[] getOutputJoints(){
		return a2scalar.getOutputJoints();
	}
	/**
	*@see FunctionalLinkage#getInputJoints
	*/
	public Coordinate[] getInputJoints(){
		return average.getInputJoints();
	}
	/**
	*Not implemented. The Adder stores no parameters.
	*/
	public double[] getParameters(){
		return null;
	}
	/**
	*Not implemented. The Adder stores no parameters.
	*/
	public void setParameters(double[] parameters){}
	/**
	*Draws an Adder Linkage.
	*@param g the graphic context to draw to.
	*/
	public void redraw(Graphics g){
		Color c= g.getColor();
		average.redraw(g);
		a2scalar.redraw(g);
		g.setColor(Color.yellow);
		Geomtry.drawJoint(g,average.getOutputJoints()[0].toPoint());
		g.setColor(c);
	}
	/**
	*Stores the active joint (the joint the mouse pointer is over)
	*/
	int activeJoint = -1;
	/**
	*@see FunctionalLinkage#mouseMoved
	*/
	public int mouseMoved(MouseEvent m){
		activeJoint = average.mouseMoved(m);
		if(activeJoint==3||activeJoint==average.output){
			average.activeJoint = -1;
		}if(activeJoint>-1) return activeJoint;
		activeJoint = a2scalar.mouseMoved(m);
		if(activeJoint!=5&&activeJoint!=a2scalar.output){
			a2scalar.activeJoint = -1;
		}if(activeJoint>-1)  activeJoint = activeJoint+6;
		return activeJoint;
	}
	/**
	*@exception MachineException .
	*@see FunctionalLinkage#mouseDragged
	*/
	public void mouseDragged(MouseEvent m) throws MachineException{
		copyCoordinates(average.dJoints,tempJoints);
		if(average.activeJoint>-1)
		try{
			average.mouseDragged(m);
			inputs[1].move(average.getOutputJoints()[0]);
			a2scalar.setInputJoints(inputs);
		}catch(MachineException e){
			copyCoordinates(tempJoints,average.dJoints);
			throw e;
		}
		else if(a2scalar.activeJoint>-1)
			a2scalar.mouseDragged(m);
	}
	final static String def = "Adder Linkage";
	/**
	*@see FunctionalLinkage#getActiveStr
	*/
	public String getActiveStr(int activeJoint){
		if(activeJoint>5)
		return a2scalar.getActiveStr(a2scalar.activeJoint);
		if(activeJoint>-1)return average.getActiveStr(average.activeJoint);
		return def;
	}
	/**
	*Copies an array of coordinates
	*The method does not prefrom any length checking.
	*@param src the source array
	*@param dst the destination array.
	*/
	static void copyCoordinates(Coordinate[] src,Coordinate[] dst){
		for(int i=0;i<src.length;i++)
			if (dst[i]==null) dst[i] = new Coordinate(src[i]);
			else dst[i].move(src[i].x,src[i].y);
	}
	/**
	*@see FunctionalLinkage#getActiveJoint
	*/
	public int getActiveJoint(){
		   return activeJoint;
	}
	/**
	*@see FunctionalLinkage#setActiveJoint
	*/
	public void setActiveJoint(int activeJoint){
		this.activeJoint = activeJoint;
	}
}
