package gov.nasa.jpl.issm;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.DoubleBuffer;

import android.app.ProgressDialog;
import android.content.Intent;
import android.opengl.GLSurfaceView;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.GestureDetector;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.OnGestureListener;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.TranslateAnimation;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.Spinner;
import android.widget.ViewFlipper;
// private static final int INVISIBLE = 0;
// Loading the ISSM library locally
// private IssmJni issmNative;
// ,sealevel;

public class ISSM extends BaseActivity implements OnClickListener,
		OnGestureListener, OnDoubleTapListener {
	// private static final int INVISIBLE = 0;
	private int screenWidth;
	private int screenHeight;
	private DoubleBuffer buff;
	// Loading the ISSM library locally
	// private IssmJni issmNative;
	private String mapName;
	private String issmFolder;
	private int size;
	private GLSurfaceView mGLView;
	private FrameLayout frame;
	private ColorMap colorMap;
	private int friction, temperature;// ,sealevel;
	private final int MINIMUM = 90;
	private final int OFFSET = 10;
	private ViewFlipper viewflipper;
	private ProgressDialog dialog;
	private ColorBar colorBar;
	private Velocity velocity;
	private SliderMenu sliders;
	private ImageView defaultMap;
	private GestureDetector mDetector;
	private Spinner spinner;
	private boolean onSimulationScreen = false;
	private String url = "http://blackhawk2.jpl.nasa.gov/issm/solve?callback=?";

	// ------------------------------------------------------------------------------------------------
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main_issm);
		transition();

		// Set up a listener for double tap.
		mDetector = new GestureDetector(this, this);
		mDetector.setOnDoubleTapListener(this);

		this.initialize();
	}

	// ----------------------------------------------------------------------------------------------
	private void initialize() {
		Bundle map = getIntent().getExtras();
		{
			if (map != null) {
				issmFolder = map.getString("pathToFile");
			}
		}
		Button homeTab = (Button) findViewById(R.id.play_tab);
		homeTab.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent i = new Intent(ISSM.this, MenuPage.class);
				startActivity(i);
				finish();
			}
		});

		Button galleryTab = (Button) findViewById(R.id.gallery_tab);
		galleryTab.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent i = new Intent(ISSM.this, GalleryImage.class);
				startActivity(i);
				finish();
			}
		});
		Button videoTab = (Button) findViewById(R.id.video_tab);
		videoTab.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// String url = "http://www.youtube.com/watch?v=KlDO0C8r_ws";
				// Intent i = new Intent(Intent.ACTION_VIEW);
				// i.setData(Uri.parse(url));
				Intent i = new Intent(ISSM.this, VideoActivity.class);
				startActivity(i);
				finish();
			}
		});
		Button aboutTab = (Button) findViewById(R.id.about_tab);
		aboutTab.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent i = new Intent(ISSM.this, AboutActivity.class);
				startActivity(i);
				finish();
			}
		});
		Button teamTab = (Button) findViewById(R.id.team_tab);
		teamTab.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// String url = "http://issm.jpl.nasa.gov/";
				// Intent i = new Intent(Intent.ACTION_VIEW);
				// i.setData(Uri.parse(url));
				// startActivity(i);

				Intent i = new Intent(ISSM.this, TeamActivity.class);
				startActivity(i);
				finish();
			}
		});

		friction = MINIMUM + OFFSET;
		// temperature = MINIMUM + OFFSET;
		// sealevel = MINIMUM + OFFSET;
		frame = (FrameLayout) findViewById(R.id.frame);
		viewflipper = (ViewFlipper) findViewById(R.id.flipper);
		// Button solve = (Button) super.findViewById(R.id.solve);
		// solve.setOnClickListener(this);
		// Button back = (Button) super.findViewById(R.id.back);
		// back.setOnClickListener(this);
		Button play = (Button) super.findViewById(R.id.play);
		play.setOnClickListener(this);
		ImageButton gl = (ImageButton) findViewById(R.id.greenland);
		gl.setOnClickListener(this);
		ImageButton art = (ImageButton) findViewById(R.id.antarctica);
		art.setOnClickListener(this);
		spinner = (Spinner) super.findViewById(R.id.spinner);
		sliders = new SliderMenu(this);
		defaultMap = (ImageView) findViewById(R.id.defaultMap);
		dialog = new ProgressDialog(this);
		colorBar = (ColorBar) findViewById(R.id.colorbar);
		// load up the ISSM library and create double buffer in java
		// which later on will be pass for native for allocation.
		// issmNative = new IssmJni();
		velocity = new Velocity();

		// set default color map to be HSV
		this.colorMap = new ColorMap();
		// create colorBar
		colorBar.setColorMap(colorMap);
		spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
			@Override
			public void onItemSelected(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {
				int item = spinner.getSelectedItemPosition();
				if (item != 0) {
					String color = (String) spinner.getItemAtPosition(item);
					colorMap.setColor(color);
					colorBar.setColorMap(colorMap);
					// drawFigure();
				}
			}

			@Override
			public void onNothingSelected(AdapterView<?> arg0) {
			}
		});

		DisplayMetrics dm = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(dm);
		screenWidth = dm.widthPixels;
		screenHeight = dm.heightPixels;
	}

	// ------------------------------------------------------------------------------------------------
	public void createModel() {
		String solution_type = "StressbalanceSolution";
		String file = "";
		if (mapName.equals("greenland")) {
			file = "greenland";
		} else {
			file = "antarctica";
		}

		// size = issmNative.createISSMModel(solution_type,issmFolder,file);
		buff = ByteBuffer.allocateDirect(size * 12 * 8)
				.order(ByteOrder.nativeOrder()).asDoubleBuffer();
	}

	// ------------------------------------------------------------------------------------------------
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater menuInflater = getMenuInflater();
		menuInflater.inflate(R.menu.issm_menu, menu);

		return true;
	}

	// ---------------------------------------------------------------------------------
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0
				&& onSimulationScreen) {
			frame.removeView(mGLView);
			viewflipper.setInAnimation(inFromLeftAnimation());
			viewflipper.setOutAnimation(outToRightAnimation());
			viewflipper.showPrevious();
			onSimulationScreen = false;
			return true;
		}
		// return to menu screen
		finish();
		return super.onKeyDown(keyCode, event);
	}

	// ---------------------------------------------------------------------------------
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		this.mDetector.onTouchEvent(event);
		// Be sure to call the superclass implementation
		return super.onTouchEvent(event);
	}

	// ---------------------------------------------------------------------------------
	@Override
	public boolean onDoubleTap(MotionEvent event) {
		((MyGLSurfaceView) mGLView).resetZoom();
		return true;
	}

	@Override
	public boolean onDoubleTapEvent(MotionEvent event) {

		return true;
	}

	@Override
	public boolean onDown(MotionEvent event) {
		return true;
	}

	@Override
	public boolean onFling(MotionEvent event1, MotionEvent event2,
			float velocityX, float velocityY) {
		return true;
	}

	@Override
	public void onLongPress(MotionEvent event) {
	}

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		return true;
	}

	@Override
	public void onShowPress(MotionEvent event) {
	}

	@Override
	public boolean onSingleTapUp(MotionEvent event) {
		return true;
	}

	@Override
	public boolean onSingleTapConfirmed(MotionEvent event) {
		return true;
	}

	// ---------------------------------------------------------------------------------
	public void onClick(View view) {
		switch (view.getId()) {
		case R.id.greenland: {
			mapName = "greenland";

			defaultMap.setImageResource(R.drawable.greenland_button);
			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
				defaultMap.setScaleX(1.12f);
				defaultMap.setScaleY(0.92f);
				defaultMap.setAlpha(1.0f);
			} else {
				defaultMap.setAlpha(1);
			}
			colorBar.setVisibility(View.INVISIBLE);
			viewflipper.setInAnimation(inFromRightAnimation());
			viewflipper.setOutAnimation(outToLeftAnimation());
			viewflipper.showNext();
			defaultMap.setVisibility(View.VISIBLE);
			onSimulationScreen = true;
			// create FemModel in native code and return the size of the model
			this.createModel();
			break;
		}
		case R.id.antarctica: {
			mapName = "antarctica";
			defaultMap.setImageResource(R.drawable.antarctica_button);
			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
				defaultMap.setAlpha(1.0f);
			} else {
				defaultMap.setAlpha(1);
			}
			colorBar.setVisibility(View.INVISIBLE);
			viewflipper.setInAnimation(inFromRightAnimation());
			viewflipper.setOutAnimation(outToLeftAnimation());
			viewflipper.showNext();
			defaultMap.setVisibility(View.VISIBLE);
			onSimulationScreen = true;
			// create FemModel in native code and return the size of the model
			this.createModel();
			break;
		}

		/*
		 * case R.id.back: { frame.removeView(mGLView);
		 * viewflipper.setInAnimation(inFromLeftAnimation());
		 * viewflipper.setOutAnimation(outToRightAnimation());
		 * viewflipper.showPrevious(); break; }
		 */
		/*
		 * case R.id.solve: { friction = sliders.getFric();
		 * System.out.println(friction); new
		 * CalculationTask().execute(friction); break; }
		 */
		case R.id.play: {
			final PopupWindow popupWindow = new PopupWindow(sliders,
					screenWidth * 4 / 5, screenHeight * 2 / 5, true);
			popupWindow.showAtLocation(sliders, Gravity.CENTER, 0, 0);

			Button dismiss = (Button) sliders.findViewById(R.id.exitSetting);
			dismiss.setOnClickListener(new Button.OnClickListener() {
				public void onClick(View v) {
					friction = sliders.getFric();
					temperature = sliders.getTemp();
					// temperature = sliders.getTemp();
					// sealevel = sliders.getSea();
					popupWindow.dismiss();
					System.out.println("Friction = " + friction);
					// new CalculationTask().execute(friction,temperature);
				}
			});
		}
		}
	}

	// ----------------------------------------------------------------------------------
	public void drawFigure() {
		frame.removeView(mGLView);
		mGLView = new MyGLSurfaceView(this, buff, size, colorMap, velocity);
		colorBar.setVelocity(velocity.getVmax(), velocity.getVmin());
		colorBar.invalidate();
		colorBar.setVisibility(View.VISIBLE);
		frame.addView(mGLView);
	}

	// ------------------------------------------------------------------------------------
	// AsyncTask will allow to display while doing some task in the background
	private class CalculationTask extends AsyncTask<Integer, Integer, Boolean> {
		@Override
		protected Boolean doInBackground(Integer... target) {
			Thread thread = new Thread() {
				public void run() {
					for (int i = 0; i <= 100; i += 5) {
						try {
							Thread.sleep(300);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						publishProgress(i);
					}
				}
			};
			thread.start();
			// issmNative.solveISSMModel(target[0],buff);
			// System.out.println("temperature = " + target[1]);
			// issmNative.solveISSMModel(target[0],target[1],buff);
			return true;
		}

		protected void onPreExecute() {
			super.onPostExecute(null);
			dialog.setCancelable(true);
			dialog.setMessage("Running ISSM simulation. Please Wait ...");
			dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			dialog.setProgress(0);
			dialog.setMax(100);
			dialog.show();
		}

		protected void onProgressUpdate(Integer... value) {
			super.onProgressUpdate();
			dialog.setProgress(value[0]);
			if (value[0] == 100) {
				dialog.dismiss();
				if (defaultMap.getDrawable().isVisible() == true)
					fadeImage();
			}
		}

		protected void onPostExecute(Boolean result) {
			super.onPostExecute(result);
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if (result) {
				drawFigure();
			}

		}

	}

	// -------------------------------------------------------------------------------------

	@Override
	public void onBackPressed() {
		Intent i = new Intent(ISSM.this, MenuPage.class);
		startActivity(i);
		finish();
	}

	// -----------------------------------------------------------------------------------
	private void fadeImage() {
		Animation anim = AnimationUtils.loadAnimation(this, R.anim.fade_out);
		anim.reset();
		defaultMap.clearAnimation();
		defaultMap.startAnimation(anim);
		defaultMap.setVisibility(View.GONE);
	}

	// Below are implementation for the animation between map selection and core
	// computation

	private Animation inFromRightAnimation() {

		Animation inFromRight = new TranslateAnimation(
				Animation.RELATIVE_TO_PARENT, +1.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f);
		inFromRight.setDuration(500);
		inFromRight.setInterpolator(new AccelerateInterpolator());
		return inFromRight;
	}

	private Animation outToLeftAnimation() {
		Animation outtoLeft = new TranslateAnimation(
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, -1.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f);
		outtoLeft.setDuration(500);
		outtoLeft.setInterpolator(new AccelerateInterpolator());
		return outtoLeft;
	}

	private Animation inFromLeftAnimation() {
		Animation inFromLeft = new TranslateAnimation(
				Animation.RELATIVE_TO_PARENT, -1.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f);
		inFromLeft.setDuration(500);
		inFromLeft.setInterpolator(new AccelerateInterpolator());
		return inFromLeft;
	}

	private Animation outToRightAnimation() {
		Animation outtoRight = new TranslateAnimation(
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, +1.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f);
		outtoRight.setDuration(500);
		outtoRight.setInterpolator(new AccelerateInterpolator());
		return outtoRight;
	}
	// -------------------------------------------------------------------------------------------
}
// ///////////////////////////////////////////////////////////////////////////////////////////
