import java.awt.*;
import java.util.*;
import java.lang.Math;

public class ParamSurface //superclass
{
	public double x(double u, double v){return 0;}	
	public double y(double u, double v){return 0;}	
	public double z(double u, double v){return 0;}
	
	public double[][] getShape(){return null;}
	public void setShape(double Matrix[][]){}
	public double[] getCenter(){return null;}
	public void setCenter(double Array[]){}	
	public double getRadius(){return 0;}

	final int COORD_X = 0;
	final int COORD_Y = 1;
	final int COORD_Z = 2;	

	final int LINES_OFF = 0;
	final int LINES_ON = 1;
	final int LINES_MESH = 2;
	
	static final int ROTATE_X = 0;
	static final int ROTATE_Y = 1;
	static final int ROTATE_Z = 2;

	double focus = 400;
	int iWidth, iHeight;
	boolean bToggle = true;
	
	static Matrix3D_FK Matrix3D_FK = new Matrix3D_FK();
	
	public ParamSurface()
	{

	}

	public void draw(Graphics g, double dEpsilon, int width, int height, Color clr, int iLines)
		//will draw the entire parametric surface
		//keep a counter starting at 0, whenever drawquad is called, increment
		
		//this will not loop through u and v, this will go through the sphere
		//matrix and 
	{	
		iWidth = width;
		iHeight = height;
		int iBound = (int)((1.0/dEpsilon)*(1.0/dEpsilon));
		
		double vector1[], vector2[], vector3[], vector4[];
		
		int len = getShape().length;
		
		for (int i=0; i<(len-(1/dEpsilon)); i++)
		{
			vector1	= getShape()[i];
			if (((i+1)%(1/dEpsilon)) == 0)
			{
				vector2	= getShape()[(int)(i+1-(1/dEpsilon))%len];
				vector3 = getShape()[(i+1)%len];
			}
			else
			{
				vector2	= getShape()[(int)((i+1)%len)];
				vector3	= getShape()[(int)(((i+1)+(1/dEpsilon))%len)];
			}
			vector4	= getShape()[(int)((i+(1/dEpsilon))%len)];
			
	 		drawQuad(vector1, vector2, vector3, vector4, g, clr, dEpsilon, iLines);
		}
	}
	
	public void drawQuad(double[] Point1, double[] Point2, double[] Point3,
			double[] Point4, Graphics g, Color clr, double dEpsilon, int iLines)
		//change this so it takes in four vectors instead of this hippy BS =D
		//points are vectors with [X][Y][Z][1]
	{
		int CoordX[] = {(int)Point1[0], (int)Point2[0], (int)Point3[0], (int)Point4[0]};
		int CoordY[] = {(int)Point1[1], (int)Point2[1], (int)Point3[1], (int)Point4[1]};
		int CoordZ[] = {(int)Point1[2], (int)Point2[2], (int)Point3[2], (int)Point4[2]};
		
		for (int i=0; i<4; i++)
		{
			CoordX[i] = (int)ViewPort(Perspective(CoordX[i], CoordZ[i]), COORD_X);
			CoordY[i] = (int)ViewPort(Perspective(CoordY[i], CoordZ[i]), COORD_Y);
		}

		switch (iLines)
		{
			case LINES_OFF:
			{
				g.setColor(clr);
				g.fillPolygon(CoordX, CoordY, 4);
				break;
			}							
			case LINES_ON:
			{
				g.setColor(clr);
				g.fillPolygon(CoordX, CoordY, 4);
				g.setColor(Color.white);
				g.drawPolygon(CoordX, CoordY, 4);
				break;
			}
			case LINES_MESH:
			{
				g.setColor(Color.white);
				g.drawPolygon(CoordX, CoordY, 4);
				break;
			}
		}
	}
	
	public double ViewPort(double Coord, int column)
		//this will copy an array passed in, in this case it will be an array of
		//X or Y coordinates
	{
		double TempCoord = Coord;
		if (column == COORD_X)
			TempCoord += iWidth/2;
		else if (column == COORD_Y)
			TempCoord += iHeight/2;

		return TempCoord;
	}
	
	public double Perspective(double Coord, double z)
	{
		Coord = (focus * Coord)/(focus - z);
		return Coord;
	}
	
	public static void Translate(double Matrix[][], double a, double b, double c)
	{
		Matrix3D_FK.Translate(Matrix, a, b, c);
	}
	
	public static void Rotate(double Matrix[][], double theta, int DirRotate)
	{
		if (DirRotate == ROTATE_X)
			Matrix3D_FK.RotateX(Matrix, theta);
		if (DirRotate == ROTATE_Y)
			Matrix3D_FK.RotateY(Matrix, theta);
		if (DirRotate == ROTATE_Z)
			Matrix3D_FK.RotateZ(Matrix, theta);
	}
	
	public static void Scale(double Matrix[][], double a, double b, double c)
	{
		Matrix3D_FK.Scale(Matrix, a, b, c);
	}

	public static void Multiply(double MatrixA[][], double MatrixB[][])
	{
		Matrix3D_FK.MultiplyMatrix(MatrixA, MatrixB);
	}
	
	public void Transform(double Matrix[][], double MatrixShape[][])
	{
		int len = MatrixShape.length;
		double Center[] = getCenter();
		
		for (int i=0; i<len; i++)
			Matrix3D_FK.Transform(Matrix, MatrixShape[i]);
		setShape(MatrixShape);
		
		Matrix3D_FK.Transform(Matrix, Center);
		setCenter(Center);
	}
	public void setBounds(int iHeight, int iWidth)
	{
		this.iHeight = iHeight;
		this.iWidth = iWidth;
	}
}