package com.example.distmeasapp;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class CameraMeas extends Activity implements View.OnClickListener, SensorEventListener {

	private static final int M_CAMERA = 0;
	private static final int M_SHORTMEAS = 1;
	private static final int M_LONGMEAS = 2;
	private static final int M_HELP = 3;
	private static final int M_EXIT = 4;
	private int state;
	private float []magn = new float[3];
	private float []accel = new float[3];
	private float []result = new float[3];
	private Camera mCamera;
	private CameraPreview mPreview;
    private SensorManager manager;
    private boolean magn_rdy = false;
    private boolean accel_rdy = false;
    private double roll1 = -1000, roll2, angle, angle2, an, a, b;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.camera_meas);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		manager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
		
		// pripojeni kamery
	    try {
	        mCamera = Camera.open(); // zalozeni instance Camera
	    }
	    catch (Exception e){
	    	Toast.makeText(CameraMeas.this, "Fotoaparát není k dispozici"+e.getMessage(), Toast.LENGTH_SHORT ).show();
	    }
	    // vytvoreni preview
		mPreview = new CameraPreview(this, mCamera);
		FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
		preview.addView(mPreview);

		// zavedeni odchytavaciho tlacitka
		Button captureButton = (Button) findViewById(R.id.button_capture);
		//captureButton.setOnClickListener(this);
		captureButton.setOnClickListener(this);
		final Button methodButton = (Button) findViewById(R.id.button_method);
		methodButton.setOnClickListener(new View.OnClickListener() {
		
			@Override
			public void onClick(View v) {
				TextView view2 = (TextView) findViewById(R.id.textView2);
				if(state==0) {
					state=1;
					view2.setText("Metoda: měření obsahu");
				} else {
					state=0;
					view2.setText("Metoda: měření výšky");
				}
			}
		});
	}
	
	@Override
    public void onClick(View v) {
			magn_rdy = false;
			accel_rdy = false;
			String txt;
			double height, dist1, dist2, content;
			TextView view1 = (TextView) findViewById(R.id.textView1);
			String s = "";
			EditText et;
			et = ((EditText) findViewById(R.id.editText1));
			// editovatelnost vysky
			try {
				  txt = et.getText().toString();
				  height = Double.parseDouble(txt);
				} catch (NumberFormatException e) {
				  // pokud se nepodari nasadit uzivatelem zadavanou hodnotu
					height = 1.5;
					et.setText("1.5");
				}
			
			if(state==0) {
				// neni proveden prvni krok
				if(roll1==-1000) {
					// vystredeni nulove roviny
					roll1 = (Math.PI / 2) + result[2];

					if (Math.tan(roll1) > 4 || Math.tan(roll1) < -2) {
						Toast.makeText(CameraMeas.this, "Postav se dále od zaměřovaného objektu! Měření bylo zresetováno.", Toast.LENGTH_SHORT ).show();
						roll1 = -1000;
						return;
					} else {
						// vypocet vzdalenosti od objektu
						dist1 = height / Math.tan(roll1);
						s = String.format( "Vzdálenost: %.2f m", dist1 );
					}
				} else {
					// vystredeni nulove hodnoty
					double roll2 = - result[2] - (Math.PI / 2);
					// vypocet vzdalenosti od objektu
					dist1 = height / Math.tan(roll1);
					// vypocet vysky objektu
					dist2 = height * (Math.tan(roll2) + Math.tan(roll1)) / Math.tan(roll1);
					s = String.format( "Vzdálenost: %.2f m\nVýška: %.2f m", dist1, dist2 );
					roll1 = -1000;
				}
			} else {
				// neni proveden prvni krok
				if(roll1==-1000) {
					// vystredeni nulove roviny
					roll1 = (Math.PI / 2) + result[2];
					angle = Math.toDegrees(result[0]);
					if (Math.tan(roll1) > 4 || result[2] < -(Math.PI / 2)) {
						Toast.makeText(CameraMeas.this, "Postav se dále od zaměřovaného objektu! Měření bylo zresetováno.", Toast.LENGTH_SHORT ).show();
						roll1 = -1000;
						angle = 0;
						return;
					} else {
						// vypocet vzdalenosti od objektu
						dist1 = height / Math.tan(roll1);
						s = String.format("* Vzdálenosti bodů *\nI.bod: %.2f m", dist1, angle);
					}
				} else {
					// vystredeni nulove hodnoty
					roll2 = (Math.PI / 2) + result[2];
					angle2 = Math.toDegrees(result[0]);

					if(angle > angle2) {
						angle = (angle2 < -90)?(360 - angle - angle2):(angle - angle2);
					} else {
						angle = (angle < -90)?(360 - angle2 - angle):(angle2 - angle);
					}
					angle = Math.abs((angle>180)?(360 - angle):(angle));
					an = angle;
					if (Math.tan(roll2) > 4 || result[2] < -(Math.PI / 2)) {
						Toast.makeText(CameraMeas.this, "Postav se dále od zaměřovaného objektu! Měření bylo zresetováno.", Toast.LENGTH_SHORT ).show();
						roll1 = -1000;
						angle = 0;
						angle2 = 0;
						return;
					} else {
						// vypocet vzdalenosti od objektu
						dist1 = height / Math.tan(roll1);
						dist2 = height / Math.tan(roll2);
						
						if(dist1 > dist2) {
							if(angle < 90) {
								a = Math.abs(dist2 * Math.sin(angle));
								b = Math.abs(dist1 - Math.sqrt((dist2 * dist2) - (a * a)));
							} else {
								angle = Math.PI - angle;
								a = Math.abs(dist2 * Math.sin(angle));
								b = Math.abs(dist1 + Math.sqrt((dist2 * dist2) - (a * a)));
							}
							content = a * b;
						} else {
							if(angle < 90) {
								a = Math.abs(dist1 * Math.sin(angle));
								b = Math.abs(dist2 - Math.sqrt((dist1 * dist1) - (a * a)));
							} else {
								angle = Math.PI - angle;
								a = Math.abs(dist1 * Math.sin(angle));
								b = Math.abs(dist2 + Math.sqrt((dist1 * dist1) - (a * a)));
							}
							content = a * b;							
						}
						s = String.format("* Vzdálenosti bodů *\nI.bod: %.2f m\nII.bod: %.2f m\nRotace: %.2f ° (%.2f rad)\nObsah plochy: %.2f m^2", dist1, dist2, an, an / (180 / Math.PI), content);
					}
					roll1 = -1000;
					angle = 0;
					angle2 = 0;
					a = 0;
					b = 0;
					content = 0;
				}
			}
			view1.setText(s);
    }	

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		menu.add(0, M_CAMERA,0, R.string.menu0);
		menu.add(0, M_SHORTMEAS,0, R.string.menu1);
		menu.add(0, M_LONGMEAS,0, R.string.menu2);
		menu.add(0, M_HELP,0, R.string.menu3);
		menu.add(0, M_EXIT,0, R.string.menu4);
		return true;
	}

	@Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) {
    	switch(item.getItemId()) {
        case M_CAMERA:
        	startActivity(new Intent(this, CameraMeas.class));
        	return true;
        case M_SHORTMEAS:
        	startActivity(new Intent(this, ShortMeas.class));
        	return true;
        case M_LONGMEAS:
        	startActivity(new Intent(this, LongMeas.class));
        	return true;
        case M_HELP:
        	startActivity(new Intent(this, Help.class));
        	return true;
        case M_EXIT:
        	finish();
        	return true;
        default:
            return super.onOptionsItemSelected(item);
	    }
    }
	

    private void releaseCamera(){
        if (mCamera != null){
            mCamera.release();
            mCamera = null;
        }
    }

	@Override
	public void onAccuracyChanged(Sensor arg0, int arg1) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onSensorChanged(SensorEvent event) {
		switch (event.sensor.getType()) {
		case Sensor.TYPE_MAGNETIC_FIELD:
				magn = event.values.clone();
				magn_rdy = true;
			break;
		case Sensor.TYPE_ACCELEROMETER:
				accel = event.values.clone();
				accel_rdy = true;
			break;
		default:
			return;
		}
		
		if (magn != null && accel != null && magn_rdy && accel_rdy) {
			float[] rot = new float[16];
	        float[] axis = new float[16];
	        SensorManager.getRotationMatrix(rot, axis, accel, magn);
	        SensorManager.getOrientation(rot, result);
			ProgressBar view = (ProgressBar) findViewById(R.id.progressBar1);
			// prepocet radianu na data pro progressBar
			view.setProgress((int) (1000 * (result[1] + Math.PI / 2) / (Math.PI)));
			TextView view3 = (TextView) findViewById(R.id.textView3);
			String r = "X: " + Math.round(Math.toDegrees(result[0])) + "°   Y: " + Math.round(Math.toDegrees(result[1])) + "°   Z: " + Math.round(Math.toDegrees((Math.PI / 2)+result[2])) + "°";
			view3.setText(r);
		}
	}
	
	@Override
	  protected void onResume() {
	    super.onResume();
	    // registrace tridy jako sledovac orientace a akcelerace
	    manager.registerListener(this,
	    manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
	    manager.SENSOR_DELAY_NORMAL);
	    
	    manager.registerListener(this,
	    manager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
	    manager.SENSOR_DELAY_NORMAL);

	  }

	  @Override
	  protected void onPause() {
	    // odregistrace sledovace
	    super.onPause();
	    manager.unregisterListener(this);
        releaseCamera();
	  }
	  
}
