package gov.nasa.jpl.issm;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.DoubleBuffer;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.util.FloatMath;
import android.view.MotionEvent;

public class MyGLSurfaceView extends GLSurfaceView {
	private MyGLRenderer mRend;
	private DoubleBuffer db;
	private int size;
	double vmax = 0, vmin = 0;
	final int firstVelocity = 9;
	ColorMap colorMap;
	Velocity velocity;
	// pinch to zoom
	float oldDist = 100.0f;
	float newDist;

	int mode = 0;

	public MyGLSurfaceView(Context context, DoubleBuffer db, int size,
			ColorMap colorMap, Velocity velocity) {
		super(context);
		// Create an OpenGL ES 2.0 context.
		setEGLContextClientVersion(2);
		this.db = db;
		this.size = size;
		this.colorMap = colorMap;
		this.velocity = velocity;
		vmin = db.get(firstVelocity);
		findMinMaxVelocity();
		intialize();
		this.velocity.setVmin(vmin);
		this.velocity.setVmax(vmax);
	}

	private void intialize() {
		final int MAX_VERTICES = 21;
		float f[][] = new float[size][MAX_VERTICES];
		// indexes prefer to velocity at each vertices of triangles.
		double alpha1, alpha2, alpha3;
		float xmin, xmax, ymin, ymax;
		final double XSCALE_FACTOR = 1;
		final double YSCALE_FACTOR = 1.2;
		RGB rgb = new RGB();

		for (int i = 0; i < size; i++) {
			f[i][0] = (float) db.get(12 * i + 0);
			f[i][1] = (float) db.get(12 * i + 1);
			f[i][2] = (float) db.get(12 * i + 2);
			f[i][7] = (float) db.get(12 * i + 3);
			f[i][8] = (float) db.get(12 * i + 4);
			f[i][9] = (float) db.get(12 * i + 5);
			f[i][14] = (float) db.get(12 * i + 6);
			f[i][15] = (float) db.get(12 * i + 7);
			f[i][16] = (float) db.get(12 * i + 8);

			f[i][6] = 1.0f;
			f[i][13] = 1.0f;
			f[i][20] = 1.0f;

			alpha1 = getAlphaColor(db.get(12 * i + 9));
			alpha2 = getAlphaColor(db.get(12 * i + 10));
			alpha3 = getAlphaColor(db.get(12 * i + 11));

			colorMap.getRGB(alpha1, rgb);
			float r1 = rgb.getR();
			float g1 = rgb.getG();
			float b1 = rgb.getB();

			colorMap.getRGB(alpha2, rgb);
			float r2 = rgb.getR();
			float g2 = rgb.getG();
			float b2 = rgb.getB();

			colorMap.getRGB(alpha3, rgb);
			float r3 = rgb.getR();
			float g3 = rgb.getG();
			float b3 = rgb.getB();

			f[i][3] = r1;
			f[i][4] = g1;
			f[i][5] = b1;

			f[i][10] = r2;
			f[i][11] = g2;
			f[i][12] = b2;

			f[i][17] = r3;
			f[i][18] = g3;
			f[i][19] = b3;

		}

		xmin = 0;
		ymin = 0;
		xmax = 0;
		ymax = 0;

		for (int i = 0; i < size; i++) {
			if (f[i][0] < xmin)
				xmin = f[i][0];
			if (f[i][0] > xmax)
				xmax = f[i][0];

			if (f[i][1] < ymin)
				ymin = f[i][1];
			if (f[i][1] > ymax)
				ymax = f[i][1];
		}

		for (int i = 0; i < size; i++) {
			f[i][0] = (float) XSCALE_FACTOR * 2 * (f[i][0] - xmin)
					/ (xmax - xmin) - 1;
			f[i][1] = (float) YSCALE_FACTOR * 2 * (f[i][1] - ymin)
					/ (ymax - ymin) - 1;
			f[i][7] = (float) XSCALE_FACTOR * 2 * (f[i][7] - xmin)
					/ (xmax - xmin) - 1;
			f[i][8] = (float) YSCALE_FACTOR * 2 * (f[i][8] - ymin)
					/ (ymax - ymin) - 1;
			f[i][14] = (float) XSCALE_FACTOR * 2 * (f[i][14] - xmin)
					/ (xmax - xmin) - 1;
			f[i][15] = (float) YSCALE_FACTOR * 2 * (f[i][15] - ymin)
					/ (ymax - ymin) - 1;
		}

		File file1 = new File(ISSMAPP.extStorageDirectory
				+ "/ISSM/input_files/coordinate.txt");
		File file2 = new File(ISSMAPP.extStorageDirectory
				+ "/ISSM/input_files/color.txt");
		try {
			file1.createNewFile();
			file2.createNewFile();
			FileOutputStream fout1 = new FileOutputStream(file1);
			OutputStreamWriter write1 = new OutputStreamWriter(fout1);
			FileOutputStream fout2 = new FileOutputStream(file2);
			OutputStreamWriter write2 = new OutputStreamWriter(fout2);
			for (int i = 0; i < size; i++) {
				write1.append(f[i][0] + "," + f[i][1] + "," + f[i][2] + ","
						+ f[i][7] + "," + f[i][8] + "," + f[i][9] + ","
						+ f[i][14] + "," + f[i][15] + "," + f[i][16] + "\n");
				write2.append(f[i][3] + "," + f[i][4] + "," + f[i][5] + ","
						+ f[i][10] + "," + f[i][11] + "," + f[i][12] + ","
						+ f[i][17] + "," + f[i][18] + "," + f[i][19] + "\n");
			}
			write1.close();
			write2.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		mRend = new MyGLRenderer(f);
		// Set the Renderer for drawing on the GLSurfaceView
		setRenderer(mRend);

		// Render the view only when there is a change in the drawing data
		setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
	}

	private void findMinMaxVelocity() {
		for (int i = 0; i < size * 12; i++) {
			if (i % 12 == 9 || i % 12 == 10 || i % 12 == 11) {
				if (db.get(i) < vmin)
					vmin = db.get(i);
				if (db.get(i) >= vmax)
					vmax = db.get(i);
			} else
				continue;
		}

	}

	private double getAlphaColor(double velocity) {
		return (velocity - vmin) / (vmax - vmin);
	}

	private final float TOUCH_SCALE_FACTOR = 180.0f / 320;
	private float mPreviousX;

	private float mPreviousY;
	// touch events
	private final int NONE = 0;
	private final int DRAG = 0;
	private final int ZOOM = 0;

	@Override
	public boolean onTouchEvent(MotionEvent e) /* NEW STUFF */
	{
		float x = e.getX();
		float y = e.getY();
		switch (e.getAction()) {
		case MotionEvent.ACTION_DOWN: // one touch: drag
			mode = DRAG;
			// mRend.eyeX = e.getX();
			// mRend.eyeY = e.getY();
			break;

		case MotionEvent.ACTION_POINTER_DOWN: // two touches: zoom
			oldDist = spacing(e);
			if (oldDist > 10.0f)
				mode = ZOOM; // zoom
			break;

		case MotionEvent.ACTION_UP: // no mode
			mode = NONE;
			oldDist = 100.0f;
			break;

		case MotionEvent.ACTION_POINTER_UP: // no mode
			mode = NONE;
			oldDist = 100.0f;
			break;

		case MotionEvent.ACTION_MOVE: // rotation
			if (e.getPointerCount() > 1 && mode == ZOOM) {
				newDist = spacing(e);
				if (newDist > 10.0f) {
					float scale = newDist / oldDist; // scale

					// scale in the renderer
					mRend.changeScale(scale);
					oldDist = newDist;
				}
			} else if (mode == DRAG) {
				float dx = x - mPreviousX;
				float dy = y - mPreviousY;

				mRend.mAngleX += dx * TOUCH_SCALE_FACTOR;
				mRend.mAngleY += dy * TOUCH_SCALE_FACTOR;

				requestRender();
			}
			break;
		}
		mPreviousX = x;
		mPreviousY = y;
		return true;
	}

	private float spacing(MotionEvent event) /* NEW STUFF */
	{
		float x = event.getX(0) - event.getX(1);
		float y = event.getY(0) - event.getY(1);
		return FloatMath.sqrt(x * x + y * y);
	}

	public void resetZoom() {
		mRend.defaultScale();
	}

}
