package pfc.android.gestormensajeria.activities;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import pfc.android.gestormensajeria.R;
import pfc.android.gestormensajeria.dao.GestorMensajeriaDAO;
import pfc.android.gestormensajeria.entidades.Mensaje;
import pfc.android.gestormensajeria.parametros.ParametrosNavegacion;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Activity encargada de mostrar los detalles de los mensajes seleccionados y proporcionar las acciones que se pueden realizar sobre los mismos
 * @author Francisco José Lamela Rincón
 *
 */
public class DetalleActivity extends FragmentActivity{

	/**
	 * Constante con el nombre de la fuente que se usará para mostrar el contenido del mensaje
	 */
	private static final String FUENTE_DE_MENSAJE = "gloriahallelujah.ttf";
	
	/**
	 * Propiedad para manejar los accesos a datos
	 */
	private GestorMensajeriaDAO mensajeDAO = new GestorMensajeriaDAO();
	
	/**
	 * Propiedad para manejar los datos de los mensajes que se  muestran
	 */
	private Mensaje[] datos = null;
	
	/**
	 * Propiedad para manejar las fechas de los mensajes y que se usará en las reordenaciones por fecha
	 */
	private String[] fechasMensajes = null;
	
	/**
	 * Propiedad para manejar los mensajes ordenados por fecha
	 */
	private Map<String, Mensaje> mapaMensajesPorFecha = null; 
	
	/**
	 * Propiedad para manejar la lista dónde se muestran los mensajes
	 */
    private ListView lstMensajes;
	
	/**
	 * Propiedad para manejar el mensaje seleccionado en cada momento
	 */
	private Mensaje mensajeSeleccionado = null;
	
	/**
	 * Propiedad para manejar la posición en la lista del mensaje seleccionado
	 */
	private int posMensajeSeleccionado = -1;
	
	/**
	 * Propiedad para indicar si se debe actualizar la lista de mensajes debido a que se ha borrado alguno de los mensajes
	 */
	private boolean mensajesBorrados = false;
	
	/**
	 * Propiedad para manejar el orden ascendente o descendente en las ordenaciones
	 */
	private boolean ordenAscendente = true;
	
	@SuppressWarnings("unchecked")
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_detalle);
		
		mostrarMensajesDeRemitente((List<String[]>)getIntent().getSerializableExtra(ParametrosNavegacion.MENSAJES_REMITENTE), null);
		
		lstMensajes = (ListView)findViewById(R.id.LstDetalleCabeceras);
        lstMensajes.setAdapter(new AdaptadorMensajes(this));
        lstMensajes.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> list, View view, int pos, long id) {
            	posMensajeSeleccionado = pos;
            	onMensajeSeleccionado((Mensaje)lstMensajes.getAdapter().getItem(pos));
            }
        });
	}
	
	
	@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.detalle_menu, menu);
        return true;
    }
	
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		
		//Comprobamos si se está volviendo de seleccionar una plantilla
		if(resultCode == ParametrosNavegacion.PLANTILLA_OK){
			//Obtenemos el cuerpo del mensaje de la plantilla
			Bundle b = data.getExtras();	
	        String contenidoPlantilla = b.getString(ParametrosNavegacion.CONTENIDO_PLANTILLA_SELECCIONADA);
	        
	        //Si no está vacío el cuerpo del mensaje 
	        if(contenidoPlantilla != null && contenidoPlantilla.length() > 0){
	        	//Muestra las aplicaciones disponibles para la redacción del mensaje pasandole el cuerpo del mensaje
	        	lanzarDialogoDeSeleccionParaSMS(contenidoPlantilla);
	        }
		}
	}

	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
        case R.id.action_ordenar_por_fecha:
            ordenaPorFecha();
            return true;
        case R.id.action_responder:
        	//Cogemos el remitente, que es común a todos los mensajes
        	if(datos != null && datos.length > 0)
        		responderAMensaje();
            return true;
        case R.id.action_borrar:
        	borrarMensaje();
          	return true;
        default:
            return super.onOptionsItemSelected(item);
		}
	}
	
	
	@Override
	public void onBackPressed() {
		Intent intent = new Intent();
		//Creamos la información a pasar entre actividades
		Bundle b = new Bundle();
		b.putBoolean(ParametrosNavegacion.ACTUALIZAR_POR_BORRADO, mensajesBorrados);
		//Añadimos la información al intent
		intent.putExtras(b);
		setResult(ParametrosNavegacion.DETALLES_OK, intent);
		
		super.onBackPressed();
	}

	
	// ***********************  METODOS AUXILIARES  ***********************
	
	/**
	 * Carga los datos de los mensajes del remitente
	 * @param mensajes
	 */
	private void mostrarMensajesDeRemitente(List<String[]> mensajes, Mensaje[] datosActualizados){
		if(mensajes != null || datosActualizados != null){
			//Obtenemos los datos y rellenamos las colecciones
			if(datosActualizados == null)
				datos = mensajeDAO.obtenerMesajesDeRemitente(mensajes);
			else{
				datos = new Mensaje[datosActualizados.length];
				for(int i=0; i<datosActualizados.length; i++)
					datos[i] = datosActualizados[i];
			}
			
			if(datos != null){
				if(mapaMensajesPorFecha == null)
					mapaMensajesPorFecha = new HashMap<String, Mensaje>();
				mapaMensajesPorFecha.clear();

				fechasMensajes = new String[datos.length];
				for(int i=0; i<datos.length; i++){
					String fecha = invierteString(datos[i].getFechaEnMilisegundos());
					mapaMensajesPorFecha.put(fecha, datos[i]);
					fechasMensajes[i] = fecha;
				}
			}
		}
	}
	
	
	/**
	 * Ordena los resultados según su fecha de recepción	
	 */
    public void ordenaPorFecha(){
    	//Ordenamos el array de fechas
    	Arrays.sort(fechasMensajes);

    	//Dependiendo de la ordenación recorremos y asignamos en un orden u otro
    	if(ordenAscendente){
    		for(int i=0; i<fechasMensajes.length; i++)
    			datos[i] = mapaMensajesPorFecha.get(fechasMensajes[i]);
    	}else{
    		for(int i=fechasMensajes.length-1, j=0; i>=0; i--, j++)
    			datos[j] = mapaMensajesPorFecha.get(fechasMensajes[i]);
    	}
		
    	//Cambiamos el valor del orden
    	if(ordenAscendente)
    		ordenAscendente = false;
    	else
    		ordenAscendente = true;	
    	
		//Actualizamos la lista de resultados
		lstMensajes.setAdapter(new AdaptadorMensajes(this));
    }
    
    
    /**
	 * Invierte el string pasado devolviendo otro con los caracteres colocados en orden inverso 
	 * @param stringOriginal
	 * @return
	 */
	private String invierteString(String stringOriginal) {
		String stringInvertido = null;
		
		StringBuilder builder = new StringBuilder(stringOriginal);
		stringInvertido = builder.reverse().toString();

		return stringInvertido;
	}
	
	
	/**
	 * Muestra el texto del mensaje en el campo adecuado adaptando el formato de letra al tamaño del mensaje para que no haya problemas de visualización
	 * @param texto
	 */
	private void mostrarCuerpoDetalle(String texto) {
		 TextView txtDetalle = (TextView)findViewById(R.id.TxtDetalleCuerpo);
		 txtDetalle.setText(texto);
		 //Obtenemos el tipo de fuente personalizado y se lo asignamos
		 Typeface fuente = Typeface.createFromAsset(this.getAssets(), FUENTE_DE_MENSAJE);
		 txtDetalle.setTypeface(fuente);
		 //Controlamos el tamaño de la fuente segun la longitud del texto
		 if(texto.length() <= 125){
			 if(contarMayusculas(texto) > 20)
				 txtDetalle.setTextSize(Float.valueOf(15));
		 }else if(texto.length() > 125 && texto.length() < 200){
			 if(contarMayusculas(texto) > 20)
				 txtDetalle.setTextSize(Float.valueOf(11));
			 else
				 txtDetalle.setTextSize(Float.valueOf(15));
		 }else if(texto.length() >= 200)
			 txtDetalle.setTextSize(Float.valueOf(11));
	}
	
	
	/**
	 * Limpia el campo destinado a mostrar el texto del mensaje 
	 * @param texto
	 */
	private void limpiarCuerpoDetalle() {
		 TextView txtDetalle = (TextView)findViewById(R.id.TxtDetalleCuerpo);
		 txtDetalle.setText("");
	}
	
	
	/**
	 * Cuenta el numero del letras mayusculas que aparecen en el texto
	 * @param texto
	 * @return
	 */
	private int contarMayusculas(String texto) {
		int numMayusculas = 0;
		
		for(int i=0; i<texto.length(); i++){
			if(Character.isUpperCase(texto.charAt(i)))
				numMayusculas++;
		}
		
		return numMayusculas;
	}
    
	
	/**
	 * Pregunta si se desea usar una plantilla para responder al mensaje y prepara las acciones oportunas dependiendo de si se acepta o no el ofrecicimiento
	 * @param remitente
	 */
	private void responderAMensaje(){
		//Creamos el dialog para preguntar si se desea usar una plantilla
        AlertDialog.Builder dialogEliminar = new AlertDialog.Builder(this);
        dialogEliminar.setIcon(android.R.drawable.ic_dialog_alert);
        dialogEliminar.setTitle(getResources().getString(R.string.toast_titulo_usar_plantilla));
        dialogEliminar.setMessage(getResources().getString(R.string.toast_mensaje_usar_plantilla));
        dialogEliminar.setCancelable(false);
       
        //Establecemos el comportamiento cuando se responde afirmativamente
        dialogEliminar.setPositiveButton(getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() {
	        public void onClick(DialogInterface dialog, int boton) {
	        	//Lanzamos la pantalla de seleccion y gestion de plantillas
                Intent intent = new Intent(DetalleActivity.this, PlantillasActivity.class);
                //Indicamos que estamos navegando para seleccionar una plantilla
                Bundle b = new Bundle();
                b.putBoolean(ParametrosNavegacion.HABILITAR_USAR_PLANTILLA, true);
                intent.putExtras(b);
                //Iniciamos la nueva actividad
                startActivityForResult(intent, ParametrosNavegacion.PLANTILLA_OK);
	        }

        });
	       
        //Establecemos el comportamiento cuando se responde negativamente
        dialogEliminar.setNegativeButton(android.R.string.no,  new DialogInterface.OnClickListener() {
	        public void onClick(DialogInterface dialog, int boton) {
	        	//Muestra las aplicaciones disponibles para la redacción del mensaje
	        	lanzarDialogoDeSeleccionParaSMS(null);
	        }

        });
       
        //Mostramos el dialog
        dialogEliminar.show();	
	}
	

	/**
	 * Muestra las aplicaciones disponibles para la redacción del mensaje
	 * @param mensaje Si no es nulo se pasa para que sea usado como cuerpo del mensaje
	 */
	private void lanzarDialogoDeSeleccionParaSMS(String mensaje){
		//Cogemos el remitente
		String remitente = (datos != null && datos.length > 0) ? datos[0].getRemitente() : null;
		
		//Creamos el nuevo Intent que nos lleva a la redacción de SMS
		Intent smsIntent = new Intent();	        
		smsIntent.setAction(Intent.ACTION_VIEW);
		smsIntent.setType("vnd.android-dir/mms-sms");
		
		if(remitente != null)
			smsIntent.putExtra("address", remitente);
		
		//Si nos pasan un mensaje lo incluimos
		if(mensaje != null)
			smsIntent.putExtra("sms_body", mensaje);
			
		//Lanzamos la activity
		startActivity(smsIntent);
	}
	
	
	/**
	 * Establece el comportamiento al seleccionar un mensaje en la lista
	 * @param msg
	 */
	public void onMensajeSeleccionado(Mensaje msg) {
		mostrarCuerpoDetalle(msg.getTexto());
		mensajeSeleccionado = msg;
    }
	
	
	/**
	 * Borra el mensaje seleccionado previa confirmación por parte del usuario
	 */
	private void borrarMensaje() {
    	//Comprobamos que se haya seleccionado un mensaje para borrar
		if(mensajeSeleccionado != null){
			//Borramos el registro con confirmación
	        AlertDialog.Builder dialogEliminar = new AlertDialog.Builder(this);
	        dialogEliminar.setIcon(android.R.drawable.ic_dialog_alert);
	        dialogEliminar.setTitle(getResources().getString(R.string.toast_titulo_confirmacion_borrar_mensaje));
	        dialogEliminar.setMessage(getResources().getString(R.string.toast_mensaje_confirmacion_borrar_mensaje));
	        dialogEliminar.setCancelable(false);
	       
	        //Establece el comportamiento cuando se responde afirmativamente
	        dialogEliminar.setPositiveButton(getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() {
	        	public void onClick(DialogInterface dialog, int boton) {
	        		if(GestorMensajeriaDAO.borrarMensaje(mensajeSeleccionado.getId(), getContentResolver())){
			        	//Informamos al usuario de la finalizacion del procesos
			        	Toast.makeText(DetalleActivity.this, R.string.toast_confirmacion_mensaje_borrado, Toast.LENGTH_SHORT).show();
			            
			            //Actualizamos las colecciones y la lista
			        	Mensaje[] datosActualizados = new Mensaje[datos.length-1];
			        	for(int i=0, j=0; j<datos.length-1; i++, j++){
			        		//Si estamos en la posicion seleccionada nos la saltamos
			        		if(i == posMensajeSeleccionado)
			        			i++;
			        		datosActualizados[j] = datos[i];
			        	}
			        	mostrarMensajesDeRemitente(null, datosActualizados);
			        	
			        	lstMensajes.setAdapter(new AdaptadorMensajes(DetalleActivity.this));
			        	
			        	//Reinicializamos valores
			        	posMensajeSeleccionado = -1;
			        	mensajeSeleccionado = null;
			        	mensajesBorrados = true;	    
			        	
			        	limpiarCuerpoDetalle();
	        		}else
	        			Toast.makeText(DetalleActivity.this, R.string.toast_confirmacion_mensaje_borrado_error, Toast.LENGTH_SHORT).show();
	        	}

	        });

	        //Establece el comportamiento cuando se responde negativamente
	        dialogEliminar.setNegativeButton(android.R.string.no, null);
	       
	        //Muestra el diálogo
	        dialogEliminar.show();	
		}
		
	}

	
	// ***********************  CLASES E INTERFACES INTERNAS  ***********************
	
	/**
	 * Clase privada que será la encargada de mostrar cada elemento de la lista con el formato adecuado
	 * @author Francisco José Lamela Rincón
	 *
	 */
	private class AdaptadorMensajes extends ArrayAdapter<Mensaje> {
         Activity context;

         AdaptadorMensajes(Context context) {
             super(context, R.layout.listitem_mensaje, datos);
             this.context = (Activity)context;
         }

         public View getView(int position, View convertView, ViewGroup parent) {
	         LayoutInflater inflater = context.getLayoutInflater();
	         View item = inflater.inflate(R.layout.listitem_mensaje, null);
	
	         TextView lblRemitente = (TextView)item.findViewById(R.id.LblAsunto);
	         lblRemitente.setText(datos[position].getAsunto());
	
	         TextView lblNumMensajes = (TextView)item.findViewById(R.id.LblFecha);
	         lblNumMensajes.setText(datos[position].getFecha());
	
	         return(item);
         }
	}
}
