package pfc.android.gestormensajeria.dao;

import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.CommonDataKinds.Phone;

/**
 * Clase que se encarga de los accesos a BD. El resto de clases de acceso a datos se apoyan en esta para los accesos.
 * @author Francisco José Lamela Rincón
 *
 */
public class GestorMensajeriaDBAdapter {

	/**
	 * Constante para el nombre de la tabla de configuración
	 */
	public static final String NOMBRE_TABLA_CONFIGURACION = "CONFIGURACION" ;

	/**
	 * Constante para el nombre de la tabla de plantillas
	 */
	public static final String NOMBRE_TABLA_PLANTILLAS = "PLANTILLAS" ;

	/**
	 * Constante para el nombre de la tabla de grupos
	 */
	public static final String NOMBRE_TABLA_GRUPOS = "GRUPOS" ;

	
	/**
	 * Definición de los campos a obtener al acceder al id de las imagenes de contactos
	 */
	private static final String[] PHOTO_ID_PROJECTION = new String[] {
	    ContactsContract.Contacts.PHOTO_ID
	};

	/**
	 * Definición de los campos a obtener al acceder a las imagenes de contactos
	 */
	private static final String[] PHOTO_BITMAP_PROJECTION = new String[] {
	    ContactsContract.CommonDataKinds.Photo.PHOTO
	};
	
	 
	/**
	 * Constante para el códigos del parámetro de configuración para el email origen
	 */
	public static String CODIGO_EMAIL_ORIGEN = "EMAILORIGEN";
	
	/**
	 * Constante para el códigos del parámetro de configuración para el password del email origen
	 */
	public static String CODIGO_PASSWD_EMAIL_ORIGEN = "PWDEMAILORIGEN";
	
	/**
	 * Constante para el códigos del parámetro de configuración para el email destino
	 */
	public static String CODIGO_EMAIL_DESTINO = "EMAILDESTINO";
	
	/**
	 * Constante para el códigos del parámetro de configuración para el contacto destino de la alerta
	 */
	public static String CODIGO_CONTACTO_ALERTA = "CONTACTOALERTA";
	
	/**
	 * Constante para el códigos del parámetro de configuración para el mensaje de alerta
	 */
	public static String CODIGO_MENSAJE_ALERTA = "MENSAJEALERTA";
		
	
	/**
	 * Constante para el nombre del campo id de la tabla parámetros
	 */
	public static String PARAMETROS_ID = "_id";
	
	/**
	 * Constante para el nombre del campo código de la tabla parámetros
	 */
	public static String PARAMETROS_CODIGO = "_codigo";
	
	/**
	 * Constante para el nombre del campo valor de la tabla parámetros
	 */
	public static String PARAMETROS_VALOR = "_valor";
	
	/**
	 * Constante para el nombre del campo descripción de la tabla parámetros
	 */
	public static String PARAMETROS_DESCRIPCION = "_descripcion";
 
	
	/**
	 * Constante para el nombre del campo id de la tabla plantillas
	 */
	public static String PLANTILLAS_ID = "_id";
	
	/**
	 * Constante para el nombre del campo nombre de la tabla plantillas
	 */
	public static String PLANTILLAS_NOMBRE = "_nombre";
	
	/**
	 * Constante para el nombre del campo contenido de la tabla plantillas
	 */
	public static String PLANTILLAS_CONTENIDO = "_contenido";
	
	
	/**
	 * Constante para el nombre del campo id de la tabla grupos
	 */
	public static String GRUPOS_ID = "_id";
	
	/**
	 * Constante para el nombre del campo nombre de la tabla grupos
	 */
	public static String GRUPOS_NOMBRE = "_nombre";
	
	/**
	 * Constante para el nombre del campo id de contacto de la tabla grupos
	 */
	public static String GRUPOS_ID_CONTACTO = "_id_contacto";
	
	/**
	 * Constante para el nombre del campo nombre de contacto de la tabla grupos
	 */
	public static String GRUPOS_NOMBRE_CONTACTO = "_nombre_contacto";
	
	
	private Context contexto;   
	private GestorMensajeriaDBHelper dbHelper;
	private SQLiteDatabase db;
 
	/**
	 * Definimos lista de columnas de la tabla para utilizarla en las consultas a la base de datos
	 */
	private String[] columnas_parametros = new String[]{ PARAMETROS_ID, PARAMETROS_CODIGO, PARAMETROS_VALOR, PARAMETROS_DESCRIPCION} ;
	
	
	/**
	 * Definimos lista de columnas de la tabla para utilizarla en las consultas a la base de datos
	 */
	private String[] columnas_plantillas = new String[]{ PLANTILLAS_ID, PLANTILLAS_NOMBRE, PLANTILLAS_CONTENIDO} ;
	
	
	/**
	 * Definimos lista de columnas de la tabla para utilizarla en las consultas a la base de datos
	 */
	private String[] columnas_grupos = new String[]{ GRUPOS_ID, GRUPOS_NOMBRE, GRUPOS_ID_CONTACTO, GRUPOS_NOMBRE_CONTACTO} ;
	
	
	/**
	 * Constructor
	 * @param context
	 */
	public GestorMensajeriaDBAdapter(Context context)
	{
		this.contexto = context;
	}
 
	/**
	 * Abre la BD
	 * @return
	 * @throws SQLException
	 */
	public GestorMensajeriaDBAdapter abrir() throws SQLException
	{
		dbHelper = new GestorMensajeriaDBHelper(contexto);
	    db = dbHelper.getWritableDatabase();
	    return this;
	}
	
	/**
	 * Cierra la BD
	 */
	public void cerrar()
	{
		dbHelper.close();
	}
	
	/**
	 * Abre la BD
	 */
	private void abrirBD(){
		if(db == null || !db.isOpen())
			abrir();
	}
 


	// *******   METODOS DE CONSULTA   *************
	//GET DE TODOS LOS REGISTROS
	/**
	 * Crea y devuelve un cursor para la obtención de todos los regitros de la tabla cuyo nombre se pasa en la llamada
	 * @param nombreTabla
	 * @param columnas
	 * @return
	 * @throws SQLException
	 */
	private Cursor getRegistros(String nombreTabla, String[] columnas) throws SQLException{
		abrirBD();
		
		Cursor c = db.query( true, nombreTabla, columnas, null, null, null, null, null, null);
 
		//Nos movemos al primer registro de la consulta
		if (c != null) {
			c.moveToFirst();
		}
		
		return c;
	}

	/**
	 * Devuelve un cursor para la obtención de todos los regitros de la tabla de parámetros de configuracion
	 * @return
	 * @throws SQLException
	 */
	public Cursor getParametros() throws SQLException{
		return getRegistros(NOMBRE_TABLA_CONFIGURACION, columnas_parametros);
	}

	/**
	 * Devuelve un cursor para la obtención de todos los regitros de la tabla de plantillas
	 * @return
	 * @throws SQLException
	 */
	public Cursor getPlantillas() throws SQLException{
		return getRegistros(NOMBRE_TABLA_PLANTILLAS, columnas_plantillas);
	}

	/**
	 * Devuelve un cursor para la obtención de todos los regitros de la tabla de grupos
	 * @return
	 * @throws SQLException
	 */
	public Cursor getGrupos() throws SQLException{
		return getRegistros(NOMBRE_TABLA_GRUPOS, columnas_grupos);
	}

	
	//GET POR ID
	/**
	 * Crea y devuelve un cursor para la obtención del regitro de la tabla cuyo nombre se pasa en la llamada y cuyo id también es pasado en la llamada
	 * @param id
	 * @param nombreTabla
	 * @param columnas
	 * @param campoId
	 * @return
	 * @throws SQLException
	 */
	private Cursor getPorId(Integer id, String nombreTabla, String[] columnas, String campoId) throws SQLException{
		abrirBD();
		
		Cursor c = db.query( true, nombreTabla, columnas, campoId + "= '" + id + "'", null, null, null, null, null);
 
		//Nos movemos al primer registro de la consulta
		if (c != null) {
			c.moveToFirst();
		}
		return c;
	}
	
	/**
	 * Devuelve un cursor para la obtención del regitro de la tabla plantillas y cuyo id es pasado en la llamada
	 * @param id
	 * @return
	 * @throws SQLException
	 */
	public Cursor getPlantillaPorId(Integer id) throws SQLException{
		return getPorId(id, NOMBRE_TABLA_PLANTILLAS, columnas_plantillas, PLANTILLAS_ID);
	}

	/**
	 * Devuelve un cursor para la obtención del regitro de la tabla grupos y cuyo id es pasado en la llamada
	 * @param id
	 * @return
	 * @throws SQLException
	 */
	public Cursor getGrupoPorId(Integer id) throws SQLException	{
		return getPorId(id, NOMBRE_TABLA_GRUPOS, columnas_grupos, GRUPOS_ID);
	}

	
	//GET POR NOMBRE
	/**
	 * Crea y devuelve un cursor para la obtención del regitro de la tabla cuyo nombre se pasa en la llamada y cuyo campo nombre también es pasado en la llamada
	 * @param nombre
	 * @param nombreTabla
	 * @param columnas
	 * @param campoNombre
	 * @return
	 * @throws SQLException
	 */
	private Cursor getPorNombre(String nombre, String nombreTabla, String[] columnas, String campoNombre) throws SQLException{
		abrirBD();
				
		Cursor c = db.query( true, nombreTabla, columnas, campoNombre + "= '" + nombre + "'", null, null, null, null, null);
 
		//Nos movemos al primer registro de la consulta
		if (c != null) {
			c.moveToFirst();
		}
		
		return c;
	}

	/**
	 * Devuelve un cursor para la obtención del regitro de la tabla plantillas y cuyo nombre es pasado en la llamada
	 * @param nombre
	 * @return
	 * @throws SQLException
	 */
	public Cursor getPlantillaPorNombre(String nombre) throws SQLException{
		return getPorNombre(nombre, NOMBRE_TABLA_PLANTILLAS, columnas_plantillas, PLANTILLAS_NOMBRE);
	}

	/**
	 * Devuelve un cursor para la obtención del regitro de la tabla grupos y cuyo nombre es pasado en la llamada
	 * @param nombre
	 * @return
	 * @throws SQLException
	 */
	public Cursor getGrupoPorNombre(String nombre) throws SQLException{
		return getPorNombre(nombre, NOMBRE_TABLA_GRUPOS, columnas_grupos, GRUPOS_NOMBRE);
	}
	
	/**
	 * Crea y devuelve un cursor para la obtención del regitro de la tabla grupos y cuyo nombre  e id de destinatario son pasados en la llamada
	 * @param nombre
	 * @param idDestinatario
	 * @return
	 * @throws SQLException
	 */
	public Cursor getGrupoPorNombreYDestinatario(String nombre, Integer idDestinatario) throws SQLException{
		abrirBD();
				
		Cursor c = db.query( true, NOMBRE_TABLA_GRUPOS, columnas_grupos, GRUPOS_NOMBRE + "= '" + nombre + "' and " + GRUPOS_ID_CONTACTO + "= " + idDestinatario, null, null, null, null, null);
 
		//Nos movemos al primer registro de la consulta
		if (c != null) {
			c.moveToFirst();
		}

		return c;
	}

	//GET POR CODIGO
	/**
	 * Crea un cursor para la obtención de un parámetro de configuración por su código 
	 * @param codigo
	 * @return
	 * @throws SQLException
	 */
	public Cursor getParametroPorCodigo(String codigo) throws SQLException
	{
		abrirBD();
		
		Cursor c = db.query( true, NOMBRE_TABLA_CONFIGURACION, columnas_parametros, PARAMETROS_CODIGO + "= '" + codigo + "'", null, null, null, null, null);
 
		//Nos movemos al primer registro de la consulta
		if (c != null) {
			c.moveToFirst();
		}
		return c;
	}

	//OTROS GET
	/**
	 * Crea y devuelve un cursor para obtener el id de la imagen asociada al remitente pasado en la llamada
	 * @param context
	 * @param remitente
	 * @return
	 */
	public Cursor obtenerIdDeImagen(Context context, String remitente){
		Uri uri = Uri.withAppendedPath(ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI, Uri.encode(remitente));
		Cursor c = context.getContentResolver().query(uri, PHOTO_ID_PROJECTION, null, null, ContactsContract.Contacts.DISPLAY_NAME + " ASC");
		
		//Nos movemos al primer registro de la consulta
		if(c != null) 
			c.moveToFirst();
	
		return c;
	}
	
	/**
	 * Crea y devuelve un cursor para obtener la imagen asociada al remitente pasado en la llamada
	 * @param context
	 * @param idImagen
	 * @return
	 */
	public Cursor obtenerImagenAPartirDeId(Context context, Integer idImagen){
		Uri uri = ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, idImagen);
        Cursor c = context.getContentResolver().query(uri, PHOTO_BITMAP_PROJECTION, null, null, null);
		
		//Nos movemos al primer registro de la consulta
		if(c != null) 
			c.moveToFirst();
	
		return c;
	}
	
	/**
	 * Crea y devuelve un cursor para obtener el número de teléfono asociado al contacto cuyo id se pasa en la llamada
	 * @param context
	 * @param idContacto
	 * @return
	 */
	public Cursor obtenerNumeroContactoAPartirDeId(Context context, Integer idContacto){
        Cursor c = context.getContentResolver().query(Data.CONTENT_URI,
        						 new String[] {Data._ID, Data.DISPLAY_NAME, Phone.NUMBER, Phone.TYPE},
        						 Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "' AND " + Phone.NUMBER + " IS NOT NULL AND _ID = " + idContacto,
        						 null,
        						 Data.DISPLAY_NAME + " ASC");
		//Nos movemos al primer registro de la consulta
		if(c != null) 
			c.moveToFirst();
	
		return c;
	}
	
	
	// *******   METODOS DE INSERCION   *************
	/**
	 * Inserta un nuevo registro en la tabla indicada en nombreTabla
	 * @param reg
	 * @param nombreTabla
	 * @return
	 */
	private long insert(ContentValues reg, String nombreTabla){
		abrirBD();
	    
		return db.insert(nombreTabla, null, reg);
	}
	
	/**
	 * Inserta un nuevo registro en la tabla plantillas
	 * @param reg
	 * @return
	 */
	public long insertPlantilla(ContentValues reg){
	   return insert(reg, NOMBRE_TABLA_PLANTILLAS);
	}

	/**
	 * Inserta un nuevo registro en la tabla grupos
	 * @param reg
	 * @return
	 */
	public long insertGrupo(ContentValues reg){
		   return insert(reg, NOMBRE_TABLA_GRUPOS);
	}
	
	
	// *******   METODOS DE BORRADO   ************* 
	/**
	* Elimina el registro con el identificador indicado de la tabla indicada en la llamada
	*/
	private long delete(Integer id, String tabla){
		abrirBD();
		
		return db.delete(tabla, "_id=" + id, null);
	}
	
	/**
	 * Elimina el registro con el identificador indicado de la tabla plantillas
	 * @param id
	 * @return
	 */
	public long deletePlantilla(Integer id){
		return delete(id, NOMBRE_TABLA_PLANTILLAS);
	}
		
	/**
	 * Elimina el registro con el identificador indicado de la tabla grupos
	 * @param id
	 * @return
	 */
	public long deleteComponenteGrupo(Integer id){
		return delete(id, NOMBRE_TABLA_GRUPOS);
	}

	
	// *******   METODOS DE ACTUALIZACIÓN   *************
	/**
	 * Actualiza un registro de la tabla de configuración
	 * @param reg
	 * @return
	 */
	public long updateConfiguracion(ContentValues reg)
	{
		long result = 0;
       
		abrirBD();
       
		if (reg.containsKey(PARAMETROS_CODIGO))
		{
			//Obtenemos el codigo y lo borramos de los valores
			String codigo = reg.getAsString(PARAMETROS_CODIGO);
			reg.remove(PARAMETROS_CODIGO);
          
			//Actualizamos el registro con el codigo que hemos extraido 
			result = db.update(NOMBRE_TABLA_CONFIGURACION, reg, PARAMETROS_CODIGO + " = '" + codigo + "'", null); 
		}
		
		return result;
    }
		
	/**
	 * Actualiza un registro de la tabla de plantillas
	 * @param reg
	 * @return
	 */
	public long updatePlantillas(ContentValues reg)
	{
		long result = 0;
       
		abrirBD();
       
		if (reg.containsKey(PLANTILLAS_NOMBRE))
		{
			//Obtenemos el codigo y lo borramos de los valores
			String nombrePlantilla = reg.getAsString(PLANTILLAS_NOMBRE);
			reg.remove(PLANTILLAS_NOMBRE);
          
			//Actualizamos el registro con el codigo que hemos extraido 
			result = db.update(NOMBRE_TABLA_PLANTILLAS, reg, PLANTILLAS_NOMBRE + " = '" + nombrePlantilla + "'", null); 
      }
		
      return result;
    }
}
