package pfc.android.gestormensajeria.dao;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.telephony.SmsManager;

/**
 * Clase para el acceso a los datos de los SMS. Será la única encargada de acceder a BD para todo lo relacionado con los SMS.
 * @author Francisco José Lamela Rincón
  */
public class SmsDAO extends Activity{
	//Tipos de mensaje SMS
	public static final String TIPO_SMS_ENTRADA = "SMS_ENTRADA";
	public static final String TIPO_SMS_SALIDA = "SMS_SALIDA";
	
	//URL de las bandejas de mensajes
	/**
	 * Constante para la ruta a la BD donde se encuentran los sms de entrada
	 */
	private static final Uri SMS_INBOX = Uri.parse("content://sms/inbox");
	
	/**
	 * Constante para la ruta a la BD donde se encuentran las BD relacionadas con sms
	 */
	private static final Uri SMS_RAIZ = Uri.parse("content://sms/");
	
//	private static final Uri SMS_SENT = Uri.parse("content://sms/sent");
//	private static final Uri SMS_CONVERSATIONS = Uri.parse("content://sms/conversations");
	
	//Cadenas de acceso a cada una de las distintas partes de los mensajes
	/**
	 * Constante para el nombre del campo id de los SMS
	 */
	public static final String SMS_ID = "_id";
	/**
	 * Constante para el nombre del campo remitente de los SMS
	 */
	public static final String SMS_REMITENTE = "address";
	/**
	 * Constante para el nombre del campo fecha de los SMS
	 */
	public static final String SMS_FECHA = "date";
	/**
	 * Constante para el nombre del campo cuerpo del mensaje de los SMS
	 */
	public static final String SMS_CUERPO_MENSAJE = "body";
	
	public static final String SMS_TI = "thread_id";
	public static final String SMS_PERSON = "person";
	public static final String SMS_PROTOCOLO = "protocol";
	public static final String SMS_LEIDO = "read";
	public static final String SMS_ESTADO = "status";
	public static final String SMS_TIPO = "type";
	public static final String SMS_PATH_RESPUESTA_PRESENTE = "reply_path_present";
	public static final String SMS_ASUNTO = "subject";
	public static final String SMS_CENTRO_DE_SERVICIO = "service_center";
	public static final String SMS_BLOQUEADO = "locked";
	public static final String SMS_TOA = "toa";
	public static final String SMS_SC_TOA = "sc_toa";
	public static final String SMS_REPORT_DATE = "report_date";
	public static final String SMS_INDICE_EN_SIM = "index_on_sim";
	public static final String SMS_NUMERO_DE_RESPUESTA = "callback_number";
	public static final String SMS_PRIORIDAD = "priority";
	public static final String SMS_VISTO = "seen";
 
	
	/**
	 * Obtiene los mensajes registrados en el sistema en función de los criterios de filtrado pasados en la llamada
	 * @param textoBusqueda
	 * @param buscarEnRemitente
	 * @param buscarEnAsunto
	 * @param buscarEnMensaje
	 * @param fechaDesde
	 * @param fechaHasta
	 * @param cr
	 * @return
	 */
	@SuppressWarnings("deprecation")	
	public HashMap<String,List<String[]>> obtenerMensajes(String textoBusqueda, 
														  boolean buscarEnRemitente, 
														  boolean buscarEnAsunto, 
														  boolean buscarEnMensaje, 
														  Long fechaDesde, 
														  Long fechaHasta,  
														  ContentResolver cr){
		//Mapa donde vamos a devolver los resultados de la consulta
		HashMap<String,List<String[]>> mensajes = new HashMap<String,List<String[]>>();
		
		//Indicamos las columnas que queremos consultar
		String[] projection = new String[]{SMS_ID, SMS_FECHA, SMS_CUERPO_MENSAJE, SMS_REMITENTE};
		
		
		//Creamos los criterios de busqueda a partir del texto indicado y de los lugares de busqueda marcados
		String criteriosBusqueda = null;
		if(textoBusqueda != null && textoBusqueda.length() > 0){
			if(buscarEnRemitente)
				criteriosBusqueda = "upper(" + SMS_REMITENTE + ") like '%" + textoBusqueda.toUpperCase() + "%'";
			
			if(buscarEnMensaje){
				if(criteriosBusqueda == null)
					criteriosBusqueda = "upper(" + SMS_CUERPO_MENSAJE + ") like '%" + textoBusqueda.toUpperCase() + "%'";
				else
					criteriosBusqueda = criteriosBusqueda + " or upper(" + SMS_CUERPO_MENSAJE + ") like '%" + textoBusqueda.toUpperCase() + "%'";
			}
		}
		
		//Añadimos los filtros por fecha
		if(fechaDesde != null){
			if(criteriosBusqueda == null)
				criteriosBusqueda = SMS_FECHA + " >= " + fechaDesde.longValue();
			else
				criteriosBusqueda = "(" + criteriosBusqueda + ") and " + SMS_FECHA + " >= " + fechaDesde.longValue();
		}
			

		if(fechaHasta != null){
			if(criteriosBusqueda == null)
				criteriosBusqueda = SMS_FECHA + " <= " + fechaHasta.longValue();
			else
				criteriosBusqueda = "(" + criteriosBusqueda + ") and " + SMS_FECHA + " <= " + fechaHasta.longValue();
		}
			

		
		//Creamos un cursor a la bandeja de entrada de mensajes y lo abrimos
		Cursor cursorSMS = cr.query(SMS_INBOX, projection, criteriosBusqueda, null, null);		
		startManagingCursor(cursorSMS);
			
		//Recorremos el cursor y obtenemos los datos
		if(cursorSMS.moveToFirst()){
			//Hay que formatear la fecha ya que viene en milisegundos
			SimpleDateFormat formato = new SimpleDateFormat("dd/MM/yyyy - hh:mm:ss");
			
			for(int i=0; i<cursorSMS.getCount(); i++){
				//Obtenemos el remitente. Este sera el indice del mapa
				String remitente = cursorSMS.getString(cursorSMS.getColumnIndexOrThrow(SMS_REMITENTE)).toString();
				//Inicializamos la lista de mensajes del remitente en caso de ser necesario
				if(!mensajes.containsKey(remitente))
					mensajes.put(remitente, new ArrayList<String[]>());
				
				//Obtenemos los datos del mensaje
				String[] datosMensaje = new String[GestorMensajeriaDAO.TAM_DATOS_MENSAJES];
				datosMensaje[GestorMensajeriaDAO.INDICE_ID] = cursorSMS.getString(cursorSMS.getColumnIndexOrThrow(SMS_ID)).toString();
				datosMensaje[GestorMensajeriaDAO.INDICE_REMITENTE] = cursorSMS.getString(cursorSMS.getColumnIndexOrThrow(SMS_REMITENTE)).toString();
				
				long fechaEnMilisegundos = cursorSMS.getLong(cursorSMS.getColumnIndexOrThrow(SMS_FECHA));
				Date fecha = new Date(fechaEnMilisegundos);				
				datosMensaje[GestorMensajeriaDAO.INDICE_FECHA] = formato.format(fecha);
				datosMensaje[GestorMensajeriaDAO.INDICE_FECHA_EN_MILISEGUNDOS] = "" + fechaEnMilisegundos;

				//Contenido del mensaje
				String cuerpoMensaje = cursorSMS.getString(cursorSMS.getColumnIndexOrThrow(SMS_CUERPO_MENSAJE)).toString();
				datosMensaje[GestorMensajeriaDAO.INDICE_CUERPO_MENSAJE] = cuerpoMensaje;
				
				//Como los SMS no tienen asunto creamos una cadena con los primero caracteres del mensaje
				String asunto = cuerpoMensaje == null ? null : cuerpoMensaje.length() > 20 ? cuerpoMensaje.substring(0, 20) : cuerpoMensaje.substring(0, cuerpoMensaje.length()); 
				datosMensaje[GestorMensajeriaDAO.INDICE_ASUNTO] = asunto + "...";
		
				//Incluimos el mensaje en la lista del remitente
				mensajes.get(remitente).add(datosMensaje);
				
				//Nos vamos al siguiente elemento del curs
				cursorSMS.moveToNext();
			}
		}
		
		stopManagingCursor(cursorSMS);
		
		if(cursorSMS != null && !cursorSMS.isClosed())
			cursorSMS.close();
		
		return mensajes;
	}
	

	/**
	 * Borra el SMS con el id pasado en la llamada
	 * @param idBorrado
	 * @param cr
	 * @return
	 */
	public boolean borrarMensaje(String idBorrado, ContentResolver cr){
		boolean borrado = false;
		if(idBorrado != null && idBorrado.length() > 0){
			//Lanzamos el borrado
			try{
				cr.delete(Uri.parse(SMS_RAIZ + idBorrado), null, null);
				borrado = true;
			}catch (Exception e) {
				borrado = false;
			}
		}
		
		return borrado;
	}

	
	/**
	 * Envia un SMS sin necesidad de mas interacción por parte del usuario. Usa el gestor de SMS por defecto.
	 * @param destinatario String con el número de teléfono del destinatario del mensaje
	 * @param texto String con el texto del mensaje
	 */
	public void enviarSMS(String destinatario, String texto){
		if(destinatario != null && destinatario.length() > 0 && texto != null && texto.length() > 0){
			SmsManager sms = SmsManager.getDefault();
			sms.sendTextMessage(destinatario, null, texto, null, null);
		}
	}
}
