package com.ejie.p06b.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import javax.naming.NamingException;

import com.ejie.p06b.database.P06bConnector;
import com.ejie.p06b.log.P06BLog;


public class P06bDao {
	
	protected Connection con = null;
	protected Statement stmt = null;
	protected PreparedStatement pstmt = null;
	protected String sql = null;
	protected ResultSet rs = null;
	protected boolean autoCommit = true;
	
	/**
	 * Constructor por defecto
	 */
	public P06bDao() {
		super();
	}
	
	/**
	 * Constructor completo
	 * 
	 * @param con
	 *            : Objeto de tipo Connection
	 * @param stmt
	 *            : Objeto de tipo Statement
	 * @param pstmt
	 *            : Objeto de tipo PreparedStatement
	 * @param sql
	 *            : Objeto de tipo String con la consulta SQL a ejecutar
	 * @param rs
	 *            : Objeto de tipo ResultSet
	 * @param autoCommit
	 *            : Objeto de tipo boolean que indica si se debe hacer un commit
	 *            automático
	 */
	public P06bDao(Connection con, Statement stmt, PreparedStatement pstmt,
			String sql, ResultSet rs, boolean autoCommit) {
		super();
		this.con = con;
		this.stmt = stmt;
		this.pstmt = pstmt;
		this.sql = sql;
		this.rs = rs;
		this.autoCommit = autoCommit;
	}

	/**
	 * Constructor en base sólo a un objeto Connection
	 * 
	 * @param con
	 *            : Objeto de tipo Connection
	 */
	public P06bDao(Connection con) {
		super();
		this.con = con;
		this.stmt = null;
		this.pstmt = null;
		this.sql = null;
		this.rs = null;
		this.autoCommit = false;
	}
	
	/**
	 * Método de conexion. Sirve para llamar dinámicamente a métodos del DAO
	 * creando conexion nueva independiente.
	 * 
	 * @param parametros
	 *            : Objeto de tipo Properties con los parámetros de conexión a
	 *            base de datos
	 * @throws Exception
	 *             : Lanza un objeto de tipo Exception en caso de haber existido
	 *             algún problema
	 */
	public void conectar(Properties parametros) throws NamingException, SQLException {
		this.con = P06bConnector.openConnection(parametros);
		this.con.setAutoCommit(this.autoCommit);
		P06BLog.send(0,this, "(conectar) Conexión a base de datos abierta");
	}

	/**
	 * Método de conexion. Sirve para llamar dinámicamente a métodos del DAO
	 * creando conexion nueva independiente.
	 * 
	 * @param parametros
	 *            : Objeto de tipo Properties con los parámetros de conexión a
	 *            base de datos
	 * @param autocommit
	 *            : Objeto de tipo boolean que indica si se debe hacer un commit
	 *            automático
	 * @throws Exception
	 *             : Lanza un objeto de tipo Exception en caso de haber existido
	 *             algún problema
	 */
	public void conectar(Properties parametros, boolean autocommit)
			throws Exception {
		this.con = P06bConnector.openConnection(parametros);
		this.autoCommit = autocommit;
		this.con.setAutoCommit(this.autoCommit);
		P06BLog.send(0,this, "(conectar) Conexión a base de datos abierta");
	}

	/**
	 * Método de desconexión. Sirve para desconectar la conexión dinámica
	 * anteriormente creada.
	 * 
	 * @throws SQLException
	 *             : Lanza un objeto de tipo SQLException en caso de haber
	 *             existido algún problema
	 */
	public void desconectar() throws SQLException {

		if (this.autoCommit == false && !this.con.isClosed()) {
			this.stmt = this.con.createStatement();
			this.stmt.executeUpdate("COMMIT");
			this.con.setAutoCommit(this.autoCommit);
			this.stmt.close();
			P06BLog.send(0,this, "(desconectar) Commit de base de datos realizado");
		}

//		try {
			if (this.rs != null) {
				this.rs.close();
			}
			if (this.stmt != null) {
				this.stmt.close();
			}
			if (this.pstmt != null) {
				this.pstmt.close();
			}
			if (this.con != null && !this.con.isClosed()) {
				this.con.close();
			}
//			P06BLog.send(0,this, "(desconectar) Conexión a base de datos cerrada");
//		} catch (Exception excepcion) {
//			P06BLog.send(0,this, "(desconectar) Error al desconectarse de base de datos");
//		}

	}

	/**
	 * Método de rollback. Vuelve al estado anterior de base de datos,
	 * descartando los cambios sin confirmación
	 */
	public void rollback() {
		try {
			if (this.con != null && !this.con.isClosed()) {
				this.con.rollback();
			}
			P06BLog.send(0,this, "(rollback) Rollback de base de datos realizado");
		} catch (Exception excepcion) {
			P06BLog.send(0,this, "(rollback) Error al realizar el rollback de base de datos");
		}
	}

	/**
	 */
	public void fijarNumericCharacters() throws SQLException {
		this.stmt = this.con.createStatement();
		this.stmt.executeUpdate("alter session set NLS_NUMERIC_CHARACTERS = ',.'");
		this.stmt.close();
		P06BLog.send(0,this, "alter session set NLS_NUMERIC_CHARACTERS = ',.' Ok");
	}

	/**
	 * Método de rollback. Confirma los cambios realizados en base de datos
	 * 
	 * @throws SQLException
	 *             : Lanza un objeto de tipo SQLException en caso de haber
	 *             existido algún problema
	 */
	public void commit() throws SQLException {
		if (this.con != null && !this.con.isClosed()) {
			this.stmt = this.con.createStatement();
			this.stmt.executeUpdate("COMMIT");
			this.con.setAutoCommit(this.autoCommit);
			this.stmt.close();
			P06BLog.send(0,this, "(commit) Commit de base de datos realizado");
		}
	}

	/**
	 * Método que comprueba si la conexión de base de datos ya está cerrada
	 * 
	 * @return Devuelve un objeto boolean que indica si la conexión a base de
	 *         datos está cerrada (true) o no (false)
	 * @throws SQLException
	 *             : Lanza un objeto de tipo SQLException en caso de haber
	 *             existido algún problema
	 */
	public boolean isClosed() throws SQLException {
		return (this.con != null ? this.con.isClosed() : true);
	}

	/**
	 * Método que obtiene la propiedad de confirmación de cambios en base de
	 * datos de manera automática
	 * 
	 * @return Devuelve un objeto boolean que indica si la confirmación
	 *         automática de cambios en base de datos está activa (true) o no
	 *         (false)
	 */
	public boolean isAutoCommit() {
		return this.autoCommit;
	}

	/**
	 * Método que define la propiedad de confirmación de cambios en base de
	 * datos de manera automática
	 * 
	 * @param autoCommit
	 *            : Objeto de tipo boolean que indica si los cambios en base de
	 *            datos se quiere que se confirmen automáticamente o no
	 * @throws SQLException
	 *             : Lanza un objeto de tipo SQLException en caso de haber
	 *             existido algún problema
	 */
	public void setAutoCommit(boolean autoCommit) throws SQLException {
		this.autoCommit = autoCommit;
		if (this.con != null && !this.con.isClosed()) {
			this.con.setAutoCommit(this.autoCommit);
		}
	}

	/**
	 * Método que obtiene el objeto de conexión previamente creado
	 * 
	 * @return Devuelve un objeto Connection con la conexión a base de datos
	 *         previamente creada
	 */
	public Connection getCon() {
		return this.con;
	}

	/**
	 * Método que define el objeto de conexión
	 * 
	 * @param con
	 *            : Objeto de tipo Connection con la conexión a base de datos
	 */
	public void setCon(Connection con) {
		this.con = con;
	}

}
