package gov.nasa.jpl.issm;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.DoubleBuffer;
import android.opengl.GLSurfaceView;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.app.ProgressDialog;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
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.Toast;
import android.widget.ViewFlipper;


public class ISSM extends Activity implements OnClickListener
{
	//private static final int INVISIBLE = 0;
	private int screenWidth;
	private int screenHeight;
	private DoubleBuffer buff;
	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 SliderMenu sliders;
	private ImageView defaultMap;
	private Spinner spinner;
	//------------------------------------------------------------------------------------------------    
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_issm);
        this.initialize();         
    }
  //----------------------------------------------------------------------------------------------
    private void initialize()
    {
    	Bundle map = getIntent().getExtras();
        {
        	if(map!= null)
        	{
        		issmFolder = map.getString("pathToFile");
        	}
        }
    	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 setting = (Button) super.findViewById(R.id.setting);
        setting.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);

        //load up the ISSM library and create double buffer in java
        //which later on will be pass for native for allocation.
        issmNative = new IssmJni();
        
        //set default color map to be HSV
        this.colorMap = new ColorMap();
        //create colorBar
        colorBar = new ColorBar(this);
        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);
					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="DiagnosticSolution";
    	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;
    }
//---------------------------------------------------------------------------------   
    public void onClick(View view) 
	{
    	switch(view.getId())
    	{
	    	case R.id.greenland:
			{
				mapName= "greenland";
				viewflipper.setInAnimation(inFromRightAnimation());
		        viewflipper.setOutAnimation(outToLeftAnimation());
		        viewflipper.showNext();
		        //create FemModel in native code and return the size of the model
		        this.createModel();
		        break;
			}
	    	case R.id.antarctica:
			{
				mapName= "antarctica";
				viewflipper.setInAnimation(inFromRightAnimation());
		        viewflipper.setOutAnimation(outToLeftAnimation());
		        viewflipper.showNext();
		        //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.setting:
    		{
    			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();
	    	            //sealevel = sliders.getSea();
	            		popupWindow.dismiss();
	            		System.out.println("Friction = " + friction );
	            		new CalculationTask().execute(friction);
	            	}
	            });
    		}
    	}
	}
//---------------------------------------------------------------------------------- 
    public void drawFigure()
    {
    	frame.removeView(mGLView);
    	mGLView = new MyGLSurfaceView(this, buff, size, colorMap);
    	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);
			return true;
		}
		
		protected void onPreExecute()
		{
			super.onPostExecute(null);
			dialog.setCancelable(true);
			dialog.setMessage("Loading View. 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();
				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();
			
		}
	   
   }
//-----------------------------------------------------------------------------------    
   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;
	}
//-------------------------------------------------------------------------------------------	 
}
/////////////////////////////////////////////////////////////////////////////////////////////
