package pfc.android.gestormensajeria.activities;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
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.dao.GestorMensajeriaDBAdapter;
import pfc.android.gestormensajeria.parametros.ParametrosNavegacion;
import pfc.android.gestormensajeria.utiles.Mail;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.StrictMode;
import android.provider.ContactsContract;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
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.QuickContactBadge;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Activity encargada de mostrar los mensajes resultantes de la búsqueda agrupados por remitente y proporcionar las acciones que se pueden realizar sobre los mismos
 * @author Francisco José Lamela Rincón
 *
 */
public class ResultadosActivity extends FragmentActivity{
	
	/**
	 * Constante con el nombre que tendrá el archivo de copia de seguridad
	 */
	private static final String NOMBRE_ARCHIVO_COPIA_SEGURIDAD = "/copSegGesSMS.txt";
	
	/**
	 * Propiedad para manejar la ruta dónde se generará el archivo de copia de seguridad
	 */
	private String path_archivo_copia_seguridad = null;
	
	/**
	 * Propiedad dónde se indicará el texto de búsqueda introducido en la pantalla de búsquedas 
	 */
	private String textoBusqueda = null;
	
	/**
	 * Propiedad dónde se indicará el tipo de mensajería. En esta versión no tiene sentido su uso, pero se deja para posibles ampliaciones futuras.
	 */
	private String tipoMensajeria = null;
	
	/**
	 * Propiedad dónde se indicará si en la pantalla de búsqueda se marcado la búsqueda del texto en el remitente
	 */
	boolean buscarEnRemitente = false;
	
	/**
	 * Propiedad dónde se indicará si en la pantalla de búsqueda se marcado la búsqueda del texto en el asunto
	 */
	boolean buscarEnAsunto = false;
	
	/**
	 * Propiedad dónde se indicará si en la pantalla de búsqueda se marcado la búsqueda del texto en el cuerpo del mensaje
	 */
	boolean buscarEnMensaje = false;
	
	/**
	 * Propiedad dónde se indicará la fecha en milisegundos que se ha seleccionado para que se use como filtro desde
	 */
	private Long fechaDesde = null;
	
	/**
	 * Propiedad dónde se indicará la fecha en milisegundos que se ha seleccionado para que se use como filtro hasta
	 */
	private Long fechaHasta = null;

	/**
	 * Propiedad para manejar los mensajes agrupados por remitente. La clave del mapa es el remitente y el contenido un listado de mensajes de ese remitente
	 */
	private HashMap<String,List<String[]>> mensajes = null;
	
	/**
	 * Propiedad para manejar los remitentes en el listado 
	 */
	private String[] remitentes = null;
	
	/**
	 * Propiedad para manejar el listado de resultados
	 */
    private ListView lstResultados;
    
    /**
     * Propiedad para indicar el orden ascendente o descendente en la ordenación por número de mensajes
     */
    private boolean ordenAscNumMen = false;
    
    //Atributos para el envio del mail de copia de seguridad
    /**
     * Propiedad para manejar el email de origen en las copias de seguridad
     */
    private String emailOrigen;
    
    /**
     * Propiedad para manejar la contraseña del email de origen en las copias de seguridad
     */
	private String passwdEmailOrigen;
	
	/**
	 * Propiedad para manejar el email destino al que se enviarán las copias de seguridad
	 */
	private String emailDestino;
	
	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_resultados);
        
        //Obtenemos el path de la aplicación con el que localizaremos el archivo de copia de seguridad
        path_archivo_copia_seguridad = getApplicationContext().getFilesDir().getPath() + NOMBRE_ARCHIVO_COPIA_SEGURIDAD;
        
        lstResultados = (ListView)findViewById(R.id.LstResultados);
        
        Bundle b = getIntent().getExtras();
        tipoMensajeria = b.getString(ParametrosNavegacion.TIPO_MENSAJERIA_BUSQUEDA);
        //Si es nula cogemos los SMS por defecto
        if(tipoMensajeria == null)
        	tipoMensajeria = GestorMensajeriaDAO.TIPO_SMS;
        
        //Obtenemos los criterios de búsqueda que llegan desde la pantalla de búsquedas
        textoBusqueda = b.getString(ParametrosNavegacion.CADENA_BUSQUEDA);
        buscarEnRemitente = b.getBoolean(ParametrosNavegacion.BUSCAR_EN_REMITENTE);
        buscarEnAsunto = b.getBoolean(ParametrosNavegacion.BUSCAR_EN_ASUNTO);
        buscarEnMensaje = b.getBoolean(ParametrosNavegacion.BUSCAR_EN_MENSAJE);
        fechaDesde = b.getLong(ParametrosNavegacion.FECHA_DESDE) > 0 ? b.getLong(ParametrosNavegacion.FECHA_DESDE) : null;
        fechaHasta = b.getLong(ParametrosNavegacion.FECHA_HASTA) > 0 ? b.getLong(ParametrosNavegacion.FECHA_HASTA) : null;

        //Obtenemos los mensajes que cumplen los criterios pasados
        mensajes = GestorMensajeriaDAO.obtenerMensajes(tipoMensajeria, textoBusqueda, buscarEnRemitente, buscarEnAsunto, buscarEnMensaje, fechaDesde, fechaHasta, getContentResolver());

        //Montamos la lista con los resultados
        remitentes = null;
        if(mensajes != null){
        	remitentes = new String[mensajes.size()];
        	int indice = 0;
        	for(String remitente: mensajes.keySet()){
        		remitentes[indice] = remitente;
        		indice++;
        	}
        
		    lstResultados.setAdapter(new AdaptadorResultados(this));
		    lstResultados.setOnItemClickListener(new OnItemClickListener() {
		        @Override
		        public void onItemClick(AdapterView<?> list, View view, int pos, long id) {
		        	onRemitenteSeleccionado(mensajes.get((String)lstResultados.getAdapter().getItem(pos)));
		        }
		    });
        }
        
        //Permitimos el acceso a internet para poder mandar el mail
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 
        StrictMode.setThreadPolicy(policy);
        
        
    }
	
	
	@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.resultado_menu, menu);
        return true;
    }

	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
	        case R.id.action_ordenar_por_remitente:
	            ordenaPorRemitente();
	            return true;
	        case R.id.action_ordenar_por_num_mensajes:
	        	ordenaPorNumeroMensajes();
	            return true;
	        case R.id.action_copia_seguridad_por_mail:
	        	if(generarFicheroCopiaSeguridad())
	        		enviarCorreoCopiaSeguridad();
	        	else
	        		Toast.makeText(getApplicationContext(), R.string.toast_copia_seguridad_no_ok, Toast.LENGTH_LONG).show();
	            return true;
	        default:
	            return super.onOptionsItemSelected(item);
		}
	}
	
	
	@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.DETALLES_OK){
			//Obtenemos el cuerpo del mensaje de la plantilla
			Bundle b = data.getExtras();	
	        boolean actualizarPorBorrado = b.getBoolean(ParametrosNavegacion.ACTUALIZAR_POR_BORRADO);
	        
	        //Si se ha borrado debemos recargar los mensajes
	        if(actualizarPorBorrado){
		        mensajes = GestorMensajeriaDAO.obtenerMensajes(tipoMensajeria, textoBusqueda, buscarEnRemitente, buscarEnAsunto, buscarEnMensaje, fechaDesde, fechaHasta, getContentResolver());

		        remitentes = null;
		        if(mensajes != null)
		        {
		        	remitentes = new String[mensajes.size()];
		        	int indice = 0;
		        	for(String remitente: mensajes.keySet()){
		        		remitentes[indice] = remitente;
		        		indice++;
		        	}
		        }
		        
		        lstResultados.setAdapter(new AdaptadorResultados(this));
	        }
		}
	}
	
	
	// ***********************  METODOS AUXILIARES  ***********************
	
	/**
	 * Genera el fichero para la copia de seguridad a partir de los resultados obtenidos
	 * @return
	 */
	private boolean generarFicheroCopiaSeguridad() {
		boolean generacionCorrecta = false;
		try{
		    OutputStreamWriter fich = new OutputStreamWriter(openFileOutput("copSegGesSMS.txt", Context.MODE_PRIVATE));
		    generacionCorrecta = volcarResultadosAFichero(fich);
		    fich.close();
		}catch (Exception ex){
		    generacionCorrecta = false;
		}
		
		return generacionCorrecta;
	}
	
	
	/**
	 * Rellena el fichero de copias de seguridad con los datos de los mensajes obtenidos
	 * @param fich
	 * @return
	 */
	private boolean volcarResultadosAFichero(OutputStreamWriter fich){
    	if(remitentes != null && remitentes.length > 0 && mensajes != null && mensajes.size() > 0){
    		try {
	    		for(int i=0; i<remitentes.length; i++){
	    			List<String []> mensajesRemitente = mensajes.get(remitentes[i]);
	    			for(String[] mensaje: mensajesRemitente){
	    				fich.write("Remitente: " + mensaje[GestorMensajeriaDAO.INDICE_REMITENTE] + "\n");
	    				fich.write("Fecha: " + mensaje[GestorMensajeriaDAO.INDICE_FECHA] + "\n");
	    				fich.write("Mensaje: " + mensaje[GestorMensajeriaDAO.INDICE_CUERPO_MENSAJE] + "\n\n\n");
	    			}
	        	}

	    		return true;
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}

    	}else
    		return false;
    }
	
	
	/**
	 * Monta la estructura del email de copia de seguridad y realiza el envío
	 */
	private void enviarCorreoCopiaSeguridad() {
    	if(cargarDatosConfiguracion()){
    		//Creamos y rellenamos el mail
    		Mail m = new Mail(emailOrigen, passwdEmailOrigen); 
            String[] toArr = {emailDestino};
            m.setTo(toArr); 
            m.setFrom(emailOrigen); 
            m.setSubject(getString(R.string.txt_asunto_copia_seguridad) + " - " + new Date()); 
            m.setBody(getString(R.string.txt_cuerpo_copia_seguridad) + new Date()); 
       
            try { 
            	//Incluimos el archivo adjunto
            	if(path_archivo_copia_seguridad != null)
            		m.addAttachment(path_archivo_copia_seguridad);

            	//Enviamos el email
            	if(m.send()) { 
            		Toast.makeText(getApplicationContext() , R.string.toast_copia_seguridad_ok_enviada, Toast.LENGTH_LONG).show(); 
            	}else{
            		Toast.makeText(getApplicationContext(), R.string.toast_copia_seguridad_ok_no_enviada, Toast.LENGTH_LONG).show(); 
            	} 
            } catch(Exception e) { 
            	Log.e("MailApp", "Could not send email", e); 
            	Toast.makeText(getApplicationContext(), R.string.toast_copia_seguridad_ok_no_enviada, Toast.LENGTH_LONG).show(); 
            }     		
    	}else
    		Toast.makeText(getApplicationContext(), R.string.toast_copia_seguridad_ok_no_enviada, Toast.LENGTH_LONG).show();
    }

	
	/**
	 * Carga los datos de configuración necesarios para poder enviar el email de copia de seguridad
	 * @return
	 */
	private boolean cargarDatosConfiguracion() {
		boolean cargaEmailOrigenOK = false;
		boolean cargaPasswdEmailOrigenOK = false;
		boolean cargaEmailDestinoOK = false;

		//Cargamos el email de origen
		emailOrigen = GestorMensajeriaDAO.obtenerValorParametroConfiguracion(this, GestorMensajeriaDBAdapter.CODIGO_EMAIL_ORIGEN);
  		cargaEmailOrigenOK = emailOrigen != null;

      	//Cargamos el password
  		passwdEmailOrigen = GestorMensajeriaDAO.obtenerValorParametroConfiguracion(this, GestorMensajeriaDBAdapter.CODIGO_PASSWD_EMAIL_ORIGEN);
  		cargaPasswdEmailOrigenOK = passwdEmailOrigen != null;
		
  		//Cargamos el email de origen
  		emailDestino = GestorMensajeriaDAO.obtenerValorParametroConfiguracion(this, GestorMensajeriaDBAdapter.CODIGO_EMAIL_DESTINO);
  		cargaEmailDestinoOK = emailDestino != null;
		
		return cargaEmailOrigenOK && cargaPasswdEmailOrigenOK && cargaEmailDestinoOK;
	}


	/**
	 * Estable el comportamiento cuando se selecciona un remitente	
	 * @param mensajesDelRemitente
	 */
	public void onRemitenteSeleccionado(List<String[]> mensajesDelRemitente) {
		//Navegamos a la pantalla de detalles pasandole los mensajes del remitente seleccionado
		Intent i = new Intent(this, DetalleActivity.class);
		i.putExtra(ParametrosNavegacion.MENSAJES_REMITENTE, (Serializable) mensajesDelRemitente);
		startActivityForResult(i, ParametrosNavegacion.DETALLES_OK);
	}
	
	
	/**
	 * Busca la imagen asociada al remitente para mostrarla en la lista. Si no tiene imagen asociada se asocia una por defecto
	 * @param badgeRemitente
	 * @param remitente
	 */
	public void establecerImagenContacto(QuickContactBadge badgeRemitente, String remitente) {
		Bitmap imagen = GestorMensajeriaDAO.obtenerImagenDeContacto(this, remitente); 

        if (imagen != null) {
            badgeRemitente.setImageBitmap(imagen);
        }else
           	badgeRemitente.setImageResource(R.drawable.remitente);
    }
	
	
	/**
	 * Ordena alfabeticamente por remitente la lista de resultados
	 */
	private void ordenaPorRemitente(){
    	//Ordenamos el array de remitentes alfabeticamente
    	if(remitentes != null){
    		Arrays.sort(remitentes);
    		//Actualizamos la lista de resultados
    		 lstResultados.setAdapter(new AdaptadorResultados(this));
    	}
    }

	
	/**
	 * Ordena la lista de resultados por número de mensajes de cada remitente
	 */
	private void ordenaPorNumeroMensajes(){
    	//Vamos a recorrer el mapa de mensajes creando un mapa indexado por numero de mensajes y valor una lista con los remitentes que tienen ese numero de mensajes 
    	if(mensajes != null)
        {
    		Map<String, List<String>> remitentesPorNumMensajes = new HashMap<String, List<String>>();
    		for(String remitente: mensajes.keySet()){
    			int iTam = mensajes.get(remitente).size();
    			String sTam = null;
    			if(iTam < 10)
    				sTam = "00" + iTam;
    			else if(iTam < 100)
    				sTam = "0" + iTam;
    			else
    				sTam = "" + iTam;

    			//Comprobamos si ya existe la entrada en el mapa y si no es si la creamos
    			if(!remitentesPorNumMensajes.containsKey(sTam))
    				remitentesPorNumMensajes.put(sTam, new ArrayList<String>());
    			
    			remitentesPorNumMensajes.get(sTam).add(remitente);
    		}
    		
    		//Creamos un array con los numeros de mensajes y lo ordenamos
    		String[] numMensajes = new String[remitentesPorNumMensajes.size()];
    		int indice = 0;
    		for(String numMensaje: remitentesPorNumMensajes.keySet()){
    			numMensajes[indice] = numMensaje;
    			indice++;
    		}
    		Arrays.sort(numMensajes);

    		//Rellenamos de nuevo la lista de remitentes con los datos ordenados
    		remitentes = new String[mensajes.size()];
    		if(ordenAscNumMen){
    			ordenAscNumMen = false;
    			//Llegamos aqui desde una ordenacion ascendente asi que tenemos que ordenar descendente
        		indice = remitentes.length - 1;
        		for(int i = 0; i < numMensajes.length; i++){
        			for(String remitente: remitentesPorNumMensajes.get(numMensajes[i])){
        				remitentes[indice] = remitente;
        				indice--;
        			}
        		}

    		}else{
    			//Llegamos aqui como ordenacion inicial o desde una ordenacion descendente asi que tenemos que ordenar ascendente
    			ordenAscNumMen = true;
        		indice = 0;
        		for(int i = 0; i < numMensajes.length; i++){
        			for(String remitente: remitentesPorNumMensajes.get(numMensajes[i])){
        				remitentes[indice] = remitente;
        				indice++;
        			}
        		}
    		}
    		
    		//Actualizamos la lista de resultados
    		lstResultados.setAdapter(new AdaptadorResultados(this));
        }
    }



	// ***********************  CLASES E INTERFACES INTERNAS  ***********************
	
	private class AdaptadorResultados extends ArrayAdapter<String> {
		Activity context;
 
        AdaptadorResultados(Context context) {
        	super(context, R.layout.listitem_remitente, remitentes);
        	this.context = (Activity)context;
        }
 
        public View getView(int position, View convertView, ViewGroup parent) {
        	LayoutInflater inflater = context.getLayoutInflater();
	        View item = inflater.inflate(R.layout.listitem_remitente, null);
	 
	        TextView lblRemitente = (TextView)item.findViewById(R.id.LblRemitenteResultados);
	        lblRemitente.setText(remitentes[position]);
	 
	        TextView lblNumMensajes = (TextView)item.findViewById(R.id.LblNumMensajes);
	        lblNumMensajes.setText("Num.Mensajes:" + mensajes.get(remitentes[position]).size());
 
	        QuickContactBadge badgeRemitente = (QuickContactBadge) item.findViewById(R.id.badge_remitente);  
	        badgeRemitente.assignContactFromPhone(remitentes[position], false);
	        establecerImagenContacto(badgeRemitente, remitentes[position]);
	        badgeRemitente.setMode(ContactsContract.QuickContact.MODE_SMALL);  
	        
            return(item);
        }
    }
}
