import VectorObject;

public class Calculator
{

private static int operations = 0;
private VectorObject operator, val1, val2;

/*
 * werden drei objekte an den Calculator uebergeben, wird eine
 * operation ausgefuehrt.  da es (EPRog einschraenkung) nur vier
 * operationen sein duerfen, wird bei der fuenften abgebrochen.
 */
public Calculator( VectorObject val1,
		   VectorObject operator, VectorObject val2 ) throws Exception
{
	this.operator = operator;
	this.val1 = val1;
	this.val2 = val2;

	if ((++operations) > 4)	throw new Exception();
}

/*
 * der constructor mir zwei parametern wird benutzt, wenn
 * einem vektor ein negatives vorzeichen (ie. seine drei werte
 * werden invertiert) verrechnet wird.
 */
public Calculator( VectorObject operator, VectorObject val )
{
	this.operator = operator;
	this.val1 = val;
}

public VectorObject prefix() throws Exception
{
	String x, y, z;

 // geht nur bei einem vektor
	if (!val1.isVector()) throw new Exception();
 // bei vorzeichen '+' tut sich nichts
	if (operator.getC() == '+') return val1;

 // sonst werden seine drei werte invertiert
	x = Double.toString(val1.getX() * -1);
	y = Double.toString(val1.getY() * -1);
	z = Double.toString(val1.getZ() * -1);

	return new VectorObject(x, y, z);
}

private VectorObject add() throws Exception
{
	String x, y, z;

 // man kann nur zwei skalare ODER zwei vektoren addieren
	if (val1.getType() != val2.getType()) throw new Exception();

	if (val1.getType() == VectorObject.SCALAR) {
		x = Double.toString(val1.getX() + val2.getX());
		return new VectorObject(x);
	} else if (val1.getType() == VectorObject.VECTOR) {
		x = Double.toString(val1.getX() + val2.getX());
		y = Double.toString(val1.getY() + val2.getY());
		z = Double.toString(val1.getZ() + val2.getZ());
		return new VectorObject(x, y, z);
	} else throw new Exception();
} // end VectorObject add()

private VectorObject sub() throws Exception
{
	String x, y, z;

 // siehe add()
	if (val1.getType() != val2.getType()) throw new Exception();

	if (val1.getType() == VectorObject.SCALAR) {

		x = Double.toString(val1.getX() - val2.getX());
		return new VectorObject(x);

	} else if (val1.getType() == VectorObject.VECTOR) {

		x = Double.toString(val1.getX() - val2.getX());
		y = Double.toString(val1.getY() - val2.getY());
		z = Double.toString(val1.getZ() - val2.getZ());
		return new VectorObject(x, y, z);

	} else throw new Exception();
} // end VectorObject subt()

private VectorObject mult() throws Exception
{
	double dblX, dblY, dblZ;
	String x, y, z;

	if (val1.getType() == VectorObject.SCALAR) {
		if (val2.getType() == VectorObject.SCALAR) {
			x = Double.toString(val1.getX() * val2.getX());
			return new VectorObject(x);
		} else if (val2.getType() == VectorObject.VECTOR) {
			x = Double.toString(val1.getX() * val2.getX());
			y = Double.toString(val1.getX() * val2.getY());
			z = Double.toString(val1.getX() * val2.getZ());

			return new VectorObject(x, y, z);
		} else throw new Exception();
	} else if (val1.getType() == VectorObject.VECTOR) {
		if (val2.getType() == VectorObject.SCALAR) {
			x = Double.toString(val1.getX() * val2.getX());
			y = Double.toString(val1.getY() * val2.getX());
			z = Double.toString(val1.getZ() * val2.getX());

			return new VectorObject(x, y, z);
		} else if (val2.getType() == VectorObject.VECTOR) {
			dblX = val1.getY() * val2.getZ();
			dblX -= val2.getY() * val1.getZ();
			x = Double.toString(dblX);

			dblY = val1.getX() * val2.getZ();
			dblY -= val2.getX() * val1.getZ();
			y = Double.toString(dblY * -1);

			dblZ = val1.getX() * val2.getY();
			dblZ -= val2.getX() * val1.getY();
			z = Double.toString(dblZ);

			return new VectorObject(x, y, z);
		} else throw new Exception();
	} else throw new Exception();
} // end VectorObject mult()

/*
 * run() wird aus dem hauptprogramm aufgerufen.
 * liefert das ergebniss als objekt zurueck.
 */
public VectorObject run() throws Exception
{
	if (operator.getType() == VectorObject.PLUS) return add();
	else if (operator.getType() == VectorObject.MINUS) return sub();
	else if (operator.getType() == VectorObject.MULT) return mult();
	else throw new Exception();
} // end VectorObject run()

} // end class Calculator