/* 
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
 * USA.
 */
/** 
	 * Sensores.java
	 * Autor: Alberto Población Navarro
	 * Añadido al proyecto en la version v0.1.2
	 * Añadido a:
	 		* Proyecto original: http://code.google.com/p/android-vnc-viewer
	 		* Release: 39
	 * Librerias externas utilizadas: open_intents-lib.jar
	 * Referencia: http://code.google.com/p/openintents/wiki/SensorSimulator
	 */
package android.androidVNC;

import org.openintents.hardware.SensorManagerSimulator;
import org.openintents.provider.Hardware;

import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.hardware.SensorListener;
import android.hardware.SensorManager;

/**
 * Clase que se encarga de conectar con un simulador que emula movimientos del telÃ©fono.
 * Si hay movimientos de mas de 10 grados se mueve el escritorio en esa direccion
 * @author Alberto Población Navarro
 *
 */
public class Sensores{
		
	private SensorManager sensors;
	private VncCanvasActivity vncCanvasActivity;
	private VncCanvas vncCanvas;
	private SensorListener sensorlistener;
	private Notificacion notificacion;
	private AndroidLog log;
	private boolean registrar_posicion; //Flag para registrar la posicion actual en los distintos ejes.
	private float ejex, ejey, ejez; //Valor inicial eje x sensor orientacion y accelerometro
	//static private float ejeyo, ejeya, ejeyc; //Valor inicial eje y sensor orientacion y accelerometro
	//static private float ejezo, ejezc;//, ejeza; //Valor inicial eje z sensor orientacion y accelerometro
	private final int EJEX=0; //Posicion del eje x en el vector
	private final int EJEY=1; //Posicion del eje y en el vector
	private final int EJEZ=2; //Posicion del eje z en el vector
	private final int MOVER=20; //Cantidad de pixeles que se desplaza el escritorio
	static final int ACELEROMETRO =0;
	static final int ORIENTACION  =1;
	static final int BRUJULA = 2;
	private static final String TAG = "SENSORES";
	
	private static Sensores instancia = null;
	
	static synchronized Sensores Instancia(VncCanvasActivity vnccanvasactivity, VncCanvas vnccanvas){
		if (instancia == null)
			instancia = new Sensores(vnccanvasactivity, vnccanvas);
		return instancia;
	}
	/**
	 * Crea una instancia de la clase sensores, obteniendo los sensores existentes en el dispositivo.
	 * Inicializa las variables
	 * @param vnccanvasactivity
	 * @param vnccanvas
	 * @author Alberto Población Navarro
	 */
	private Sensores(final VncCanvasActivity vnccanvasactivity, VncCanvas vnccanvas){
			vncCanvas = vnccanvas;
			vncCanvasActivity = vnccanvasactivity;
			registrar_posicion=true;
			notificacion = Notificacion.Instancia(vncCanvasActivity);
			log = AndroidLog.Instancia();
		 //Con movil real: Para trabajar con dispositivo fisico, comentar las lineas entre las etiquetas <Con simulador+emulador> y
		 //descomentar la siguiente linea
    		//sensors=(SensorManager)vncCanvasActivity.getSystemService(Context.SENSOR_SERVICE);
			
		//<Con simulador+emulador>
	        // Before calling any of the Simulator data, 
	        // the Content resolver has to be set !! 
	        Hardware.mContentResolver = vncCanvasActivity.getContentResolver(); 
	        // Link sensor manager to OpenIntents Sensor simulator 
	        sensors = (SensorManager) new SensorManagerSimulator((SensorManager)vncCanvasActivity.getSystemService(Context.SENSOR_SERVICE)); 
	        
	        Intent intent = new Intent(Intent.ACTION_VIEW, 	Hardware.Preferences.CONTENT_URI); 
	        vncCanvasActivity.startActivity(intent); 
	        SensorManagerSimulator.connectSimulator();
	        //Salvo novedad, se dejan los visualización de escritorio con los sensores para verlo horizontalmnt
	        vncCanvasActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
			
	     //</Con simulador+emulador>
	       
      	    sensorlistener = new SensorListener(){
				@Override
				public void onAccuracyChanged(int sensor, int accuracy) {
					// TODO Auto-generated method stub
					//no hacer nada
				}
				@Override
				public void onSensorChanged(int sensor, float[] values) {
					/**Log.d("Sensores", "On sensor Changed: "+vncCanvasActivity.getRequestedOrientation());
					switch (vncCanvasActivity.getRequestedOrientation()) {
					case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
						vncCanvasActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
						Log.d("Sensores", "Esta en vertical lo paso a horizontal");
						break;
					case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
						vncCanvasActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
						Log.d("Sensores", "Esta en horizontal lo paso a vertical");
						
						break;
					}*/
					
					if(sensor==SensorManager.SENSOR_ORIENTATION){
						if(registrar_posicion)
						{
							ejex=values[EJEX];
							ejey=values[EJEY];
							ejez=values[EJEZ];
							registrar_posicion = false;
						}
						int scrollX=0;
						int scrollY=0;
						// Obtenemos unos valores iniciales y si hay una variacion de 10º en la horientazion movemos el escritorio							
						if(values[EJEX] > (ejex+10)) //Extremo izquierdo hacia atras	
							scrollX -= MOVER; //values[EJEY]+ejey; para moverlo mas o menos rápido
						else if (values[EJEX]+10 < ejex) //Extremos derecho hacia atras 
							scrollX +=MOVER;
						//Y -90 usamos el marge de 20 
						if(values[EJEZ] > (ejez+10))	//Pantalla hacia arriba
							scrollY -= MOVER;
						else if (values[EJEZ]+10 < ejez) //Pantalla hacia abajo 
							scrollY +=MOVER;
						if(values[EJEY] > (ejey+10)) //Giro del movil como un volante hacia la izquierda
							scrollX -= MOVER;
						else if (values[EJEY]+10 < ejey) //Giro del movil como un volante hacia la izquierda
							scrollX +=MOVER;
						//Cantidad de desplazamiento a realizar
						vncCanvasActivity.absoluteXPosition += scrollX;
						vncCanvasActivity.absoluteYPosition += scrollY;
						//Limites Eje X
						if(vncCanvasActivity.absoluteXPosition < 0){
							scrollX=0;
							vncCanvasActivity.absoluteXPosition=0;
						}
						if(vncCanvasActivity.absoluteXPosition + vncCanvas.getWidth()> vncCanvas.getImageWidth()){
							scrollX=0;
							vncCanvasActivity.absoluteXPosition-=MOVER;
						}
						//Limites Eje Y
						if(vncCanvasActivity.absoluteYPosition < 0){
							scrollY=0;
							vncCanvasActivity.absoluteYPosition=0;
						}
						if(vncCanvasActivity.absoluteYPosition + vncCanvas.getHeight() > vncCanvas.getImageHeight()){
							scrollY=0;
							vncCanvasActivity.absoluteYPosition-=MOVER;
						}
						vncCanvas.scrollBy(scrollX,scrollY);
					
					}else if(sensor==SensorManager.SENSOR_MAGNETIC_FIELD){
						//Espacio reservador para añadir un posible panning mediante la brújula
						/*Vibrator vibrador = (Vibrator)vncCanvasActivity.getSystemService("vibrator");
						if (vibrador != null){
							//vibrador.vibrate(100);
					        //vibrador.cancel();
						}else
							Toast.makeText(vncCanvasActivity, "NULL", Toast.LENGTH_SHORT).show();
						*/
							
				        //Vibrator vibrador = null;
						//
						/*int scrollX=0;
						int scrollY=0;
						if(registrar_posicion)
						{
							ejex=values[EJEX];
							ejey=values[EJEY];
							ejez=values[EJEZ];
							registrar_posicion = false;
						}
						
						if (values[EJEY]>(tamano)){
							scrollX += (vncCanvas.getImageWidth()/45)*(values[EJEY]-tamano);
							//Toast.makeText(vncCanvasActivity, "entro en el primero", Toast.LENGTH_SHORT).show();
							tamano=values[EJEY];
						}else if((values[EJEY])<tamano){
							scrollX -= (vncCanvas.getImageWidth()/45)*(tamano-values[EJEY]);
							tamano=values[EJEY];
						}
								
						//Limites en el eje X, si funciona pero no al 100%
						vncCanvasActivity.absoluteXPosition += scrollX;
						if(vncCanvasActivity.absoluteXPosition+scrollX < 0){
							scrollX=0;
							//Toast.makeText(vncCanvasActivity, "entro izq", Toast.LENGTH_SHORT).show();
							vncCanvasActivity.absoluteXPosition-=scrollX;
							
						}else if(vncCanvasActivity.absoluteXPosition+scrollX + vncCanvas.getWidth()> vncCanvas.getImageWidth()){
							
							vncCanvasActivity.absoluteXPosition=vncCanvas.getImageWidth()-vncCanvas.getWidth();
							//Toast.makeText(vncCanvasActivity, "entro dch"+vncCanvasActivity.absoluteXPosition, Toast.LENGTH_SHORT).show();
							scrollX=0;
							/*if(modo)vncCanvasActivity.absoluteXPosition-=(vncCanvas.getImageWidth()/45)*(values[EJEY]-tamano);
							else vncCanvasActivity.absoluteXPosition +=(vncCanvas.getImageWidth()/45)*(tamano-values[EJEY]);*/
						/*}else vncCanvas.scrollBy(scrollX,0); 
						*/
						
					}else if (sensor==SensorManager.SENSOR_ACCELEROMETER){
						if(registrar_posicion)
						{
							ejex=ejey=ejez=0;	
							ejex=values[EJEX];
							ejey=values[EJEY];
							//ejeza=values[EJEZ];
							registrar_posicion = false;
						}
						
						int scrollY=0;
						int scrollX=0;
						if(values[EJEY]>(ejey)){
							//dch
							scrollX = MOVER;
							vncCanvasActivity.absoluteXPosition += scrollX;
							ejey=values[EJEY];
						}else if(values[EJEY]<(ejey)){
							//izq
							scrollX = -MOVER;
							vncCanvasActivity.absoluteXPosition += scrollX;
							ejey=values[EJEY];
						}
						if(values[EJEX]< ejex){
							scrollY =-MOVER;
							vncCanvasActivity.absoluteYPosition += scrollY;
							ejex=values[EJEX];
						}else if (values[EJEX]> (ejex)){
							scrollY=MOVER;
							vncCanvasActivity.absoluteYPosition += scrollY;
							ejex=values[EJEX];
						}
						//Limites Eje X
						if(vncCanvasActivity.absoluteXPosition < 0){
							scrollX=0;
							vncCanvasActivity.absoluteXPosition=0;
						}
						if(vncCanvasActivity.absoluteXPosition + vncCanvas.getWidth()> vncCanvas.getImageWidth()){
							scrollX=0;
							vncCanvasActivity.absoluteXPosition-=MOVER;
						}
						//Limites Eje Y
						if(vncCanvasActivity.absoluteYPosition < 0){
							scrollY=0;
							vncCanvasActivity.absoluteYPosition=0;
						}
						if(vncCanvasActivity.absoluteYPosition + vncCanvas.getHeight() > vncCanvas.getImageHeight()){
							scrollY=0;
							vncCanvasActivity.absoluteYPosition-=MOVER;
						}
						vncCanvas.scrollBy(scrollX, scrollY);
					}
						
					
				}
	        };
	        quitar();

	}
	
	/**
	 * Registra las acciones que se debe hacer si se producen ciertos cambios en los sensores:
	 * Mediante el sensor orientación se realiza un movimiento de la posicion del escritorio visible moviendo el teléfono .
	 * Con el accelerómetro podemos desplazarnos por el escritorio realizando un movimiento hacia la direccion donde queramos ir. 
	 * @return Devuelve true si se consigue registrar con exito un sensor, false en caso contrario
	 * @author Alberto Población Navarro.
	 */
	public boolean registrar(int sensor){
			log.log(TAG, "Mostramos el escritorio en posición horizontal");
			notificacion.notificar("Mostramos el escritorio en posición horizontal");
			vncCanvasActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
			//En caso de que se señale la opcion correspondiente del menu se registra uno de los sensores:
	        switch (sensor) {
			case ACELEROMETRO:
				registrar_posicion=true;
				notificacion.notificar(vncCanvasActivity.getString(R.string.T_registrer_sensor), vncCanvasActivity.getString(R.string.I_accelerometer_panning));
				log.log(TAG, vncCanvasActivity.getString(R.string.I_accelerometer_panning));
				return sensors.registerListener(sensorlistener, SensorManager.SENSOR_ACCELEROMETER, SensorManager.SENSOR_DELAY_GAME);
				
			case ORIENTACION:
				registrar_posicion=true;
				notificacion.notificar(vncCanvasActivity.getString(R.string.T_registrer_sensor), vncCanvasActivity.getString(R.string.I_orientation_panning));
				log.log(TAG, vncCanvasActivity.getString(R.string.I_orientation_panning));
				return sensors.registerListener(sensorlistener, SensorManager.SENSOR_ORIENTATION);
				
			case BRUJULA:
				registrar_posicion=true;
				notificacion.notificar(vncCanvasActivity.getString(R.string.T_registrer_sensor), vncCanvasActivity.getString(R.string.I_compass_panning));
				log.log(TAG, vncCanvasActivity.getString(R.string.I_compass_panning));
				return sensors.registerListener(sensorlistener, SensorManager.SENSOR_MAGNETIC_FIELD);	
				
			default:
				new AlertDialog.Builder(vncCanvasActivity)
          		.setTitle(vncCanvasActivity.getString(R.string.no_sensor))
          		.setMessage(vncCanvasActivity.getString(R.string.no_sensor_found))
          		.setIcon(android.R.drawable.ic_dialog_alert)
          		.setPositiveButton(android.R.string.ok, null)
          		.show();
				log.log(TAG, "No se puede encontrar el sensor seleccionado");
				notificacion.notificar("No se puede encontrar el sensor seleccionado");
				vncCanvasActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
				log.log(TAG, "Orientacion de la pantalla segun la posición del telefono");
		        return false;
			}
	 }
	/**
	 * Elimina los oyentes de todos los sensores para evitar que se activen las funciones en caso de que se activen los sensores.
	 * @author Alberto Población Navarro
	 */
	public void quitar(){
		log.log(TAG, "Sensores desactivados");
		notificacion.notificar("Sensores desactivados");
		vncCanvasActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
		log.log(TAG, "Orientacion de la pantalla segun la posición del telefono");
        
		sensors.unregisterListener(sensorlistener);
		notificacion.notificar(vncCanvasActivity.getString(R.string.T_unregistrer_sensor),vncCanvasActivity.getString(R.string.T_unregistrer_sensor));
		log.log(TAG, vncCanvasActivity.getString(R.string.T_unregistrer_sensor));
		registrar_posicion=true;
		
	}
	
	/**
	 * Elimina el oyente de un sensor en concreto para evitar que se active las funciones en caso de que se active el sensore.
	 * @param sensor Senor 
	 * @author Alberto Población Navarro
	 */
	public void quitar(int sensor){
		vncCanvasActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
		log.log(TAG, "Orientacion de la pantalla segun la posición del telefono");
        
		switch (sensor) {
		case ACELEROMETRO:
			notificacion.notificar(vncCanvasActivity.getString(R.string.T_unregistrer_sensor), vncCanvasActivity.getString(R.string.I_no_accelerometer_panning));
			log.log(TAG, vncCanvasActivity.getString(R.string.I_no_accelerometer_panning));
			sensors.unregisterListener(sensorlistener, SensorManager.SENSOR_ACCELEROMETER);
			break;
		case ORIENTACION:
			notificacion.notificar(vncCanvasActivity.getString(R.string.T_unregistrer_sensor), vncCanvasActivity.getString(R.string.I_no_orientation_panning));
			log.log(TAG, vncCanvasActivity.getString(R.string.I_no_orientation_panning));
			sensors.unregisterListener(sensorlistener, SensorManager.SENSOR_ORIENTATION);
			break;
		case BRUJULA:
			notificacion.notificar(vncCanvasActivity.getString(R.string.T_unregistrer_sensor), vncCanvasActivity.getString(R.string.I_no_compass_panning));
			log.log(TAG, vncCanvasActivity.getString(R.string.I_compass_panning));
			sensors.unregisterListener(sensorlistener, SensorManager.SENSOR_MAGNETIC_FIELD);
			break;

		
		}
	}
	/**
	 * Liberamos la instancia para que se cree una nueva la proxima vez. 
	 */
	@Override
	protected void finalize(){
		instancia = null;
	}
	/**
	 * Devolvemos true si se ha creado una instancia, false en caso contrario
	 * @return valor devuelto.
	 */
	static boolean instanciado(){
		if (instancia == null)
			return false;
		else return true; 
	}
			
}
	
	
	

