package it.mice.voila.runtime.dao;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;

/**
 * Created by IntelliJ IDEA. User: zzy9v4 Date: 17-ago-2006 Time: 1.58.05 To
 * change this template use File | Settings | File Templates.
 */
public class SqlCommandOption implements InitializingBean {
	/**
	 * Default logger
	 */
	private static Log logger = LogFactory.getLog(SqlCommandOption.class);

	private String likeFilterMethod = null;
	private boolean likeFilterIgnoreCase = true;
	private boolean flushHibernateSessionImmediatly = true;
	private boolean evictHibernateElementImmediatly = true;
	private boolean evictHibernateListElementImmediatly = false;
	private boolean clearHibernateSessionBeforeUpdate = false;

	private String likeFilterMethodLeftSymbol = "";
	private String likeFilterMethodRightSymbol = "";
	private boolean raiseExceptionOnMissingColumnFlag = true;

	private String flushMode = "MANUAL";

	public final static String LIKE_FILTER_METHOD_NONE = "NONE";
	public final static String LIKE_FILTER_METHOD_BOTH = "BOTH";
	public final static String LIKE_FILTER_METHOD_LEFT = "LEFT";
	public final static String LIKE_FILTER_METHOD_RIGHT = "RIGHT";

	public String getLikeFilterMethod() {
		return likeFilterMethod;
	}

	public void setLikeFilterMethod(String likeFilterMethod) {
		this.likeFilterMethod = likeFilterMethod;
	}

	public String getLikeFilterMethodLeftSymbol() {
		return likeFilterMethodLeftSymbol;
	}

	public String getLikeFilterMethodRightSymbol() {
		return likeFilterMethodRightSymbol;
	}

	public boolean isLikeFilterIgnoreCase() {
		return likeFilterIgnoreCase;
	}

	public void setLikeFilterIgnoreCase(boolean likeFilterIgnoreCase) {
		this.likeFilterIgnoreCase = likeFilterIgnoreCase;
	}

	public boolean isFlushHibernateSessionImmediatly() {
		return flushHibernateSessionImmediatly;
	}

	public void setFlushHibernateSessionImmediatly(
			boolean flushHibernateSessionImmediatly) {
		this.flushHibernateSessionImmediatly = flushHibernateSessionImmediatly;
	}

	public boolean isEvictHibernateElementImmediatly() {
		return evictHibernateElementImmediatly;
	}

	public void setEvictHibernateElementImmediatly(
			boolean evictHibernateElementImmediatly) {
		this.evictHibernateElementImmediatly = evictHibernateElementImmediatly;
	}

	public boolean isEvictHibernateListElementImmediatly() {
		return evictHibernateListElementImmediatly;
	}

	public void setEvictHibernateListElementImmediatly(
			boolean evictHibernateListElementImmediatly) {
		this.evictHibernateListElementImmediatly = evictHibernateListElementImmediatly;
	}

	public boolean isRaiseExceptionOnMissingColumnFlag() {
		return raiseExceptionOnMissingColumnFlag;
	}

	public void setRaiseExceptionOnMissingColumnFlag(
			boolean raiseExceptionOnMissingColumnFlag) {
		this.raiseExceptionOnMissingColumnFlag = raiseExceptionOnMissingColumnFlag;
	}

	public boolean isClearHibernateSessionBeforeUpdate() {
		return clearHibernateSessionBeforeUpdate;
	}

	public void setClearHibernateSessionBeforeUpdate(
			boolean clearHibernateSessionBeforeUpdate) {
		this.clearHibernateSessionBeforeUpdate = clearHibernateSessionBeforeUpdate;
	}

	/**
	 * @return the flushMode
	 */
	public String getFlushMode() {
		return flushMode;
	}

	/**
	 * @param flushMode the flushMode to set
	 */
	public void setFlushMode(String flushMode) {
		this.flushMode = flushMode;
	}

	public void afterPropertiesSet() throws Exception {
		if (likeFilterMethod == null || likeFilterMethod.length() == 0) {
			logger
					.warn("likeFilterMethod not defined. Assume default to 'BOTH' !");
			likeFilterMethod = LIKE_FILTER_METHOD_BOTH;
		}
		if (!(likeFilterMethod.equals(LIKE_FILTER_METHOD_NONE)
				|| likeFilterMethod.equals(LIKE_FILTER_METHOD_BOTH)
				|| likeFilterMethod.equals(LIKE_FILTER_METHOD_LEFT) || likeFilterMethod
				.equals(LIKE_FILTER_METHOD_RIGHT))) {
			logger
					.error("invalid value specified for LIKE_FILTER_METHOD, valid value are: 'BOTH' (default), 'LEFT' and 'RIGHT'. Assume default to 'BOTH' !");
			likeFilterMethod = LIKE_FILTER_METHOD_BOTH;
		}
		if (likeFilterMethod.equals(LIKE_FILTER_METHOD_BOTH)
				|| likeFilterMethod.equals(LIKE_FILTER_METHOD_LEFT)) {
			likeFilterMethodLeftSymbol = "%";
		}
		if (likeFilterMethod.equals(LIKE_FILTER_METHOD_BOTH)
				|| likeFilterMethod.equals(LIKE_FILTER_METHOD_RIGHT)) {
			likeFilterMethodRightSymbol = "%";
		}
	}

	public String getStatementFilterLike(String fieldValue) {
		return getStatementFilterLike(fieldValue, true);
	}

	public String getStatementFilterLike(String fieldValue, boolean useUpper) {
		return getStatementFilterLike(fieldValue, likeFilterMethodLeftSymbol,
				likeFilterMethodRightSymbol, useUpper);
	}

	public String getStatementFilterLike(String fieldValue,
			String likeFilterMethodLeftSymbolParam,
			String likeFilterMethodRightSymbolParam) {
		return getStatementFilterLike(fieldValue,
				likeFilterMethodLeftSymbolParam,
				likeFilterMethodRightSymbolParam, true);
	}

	public String getStatementFilterLike(String fieldValue,
			String likeFilterMethodLeftSymbolParam,
			String likeFilterMethodRightSymbolParam, boolean useUpper) {
		return likeFilterMethodLeftSymbolParam
				+ (likeFilterIgnoreCase && useUpper ? fieldValue.toUpperCase()
						: fieldValue) + likeFilterMethodRightSymbolParam;
	}

	public String getStatementFilterColumn(String columnName) {
		return getStatementFilterColumn(columnName, true);
	}

	public String getStatementFilterColumn(String columnName, boolean useUpper) {
		return (likeFilterIgnoreCase && useUpper ? "UPPER(" + columnName + ")"
				: columnName);
	}

	// Utility method to get values from result set
	public String getString(Object maskAttribute, ResultSet rs,
			String columnName) throws SQLException {
		if (maskAttribute != null) {
			return getString(rs, columnName);
		}
		return null;
	}

	public String getString(ResultSet rs, String columnName)
			throws SQLException {
		try {
			return rs.getString(columnName);
		} catch (SQLException e) {
			return (String) manageException(e);
		}
	}

	public BigDecimal getBigDecimal(Object maskAttribute, ResultSet rs,
			String columnName) throws SQLException {
		if (maskAttribute != null) {
			return getBigDecimal(rs, columnName);
		}
		return null;
	}

	public BigDecimal getBigDecimal(ResultSet rs, String columnName)
			throws SQLException {
		try {
			if (rs.getObject(columnName) != null) {
				return rs.getBigDecimal(columnName);
			} else {
				return null;
			}
		} catch (SQLException e) {
			return (BigDecimal) manageException(e);
		}
	}

	public BigInteger getBigInteger(Object maskAttribute, ResultSet rs,
			String columnName) throws SQLException {
		if (maskAttribute != null) {
			return getBigInteger(rs, columnName);
		}
		return null;
	}

	public BigInteger getBigInteger(ResultSet rs, String columnName)
			throws SQLException {
		try {
			if (rs.getObject(columnName) != null) {
				return rs.getBigDecimal(columnName).toBigInteger();
			} else {
				return null;
			}
		} catch (SQLException e) {
			return (BigInteger) manageException(e);
		}
	}

	public Integer getInteger(Object maskAttribute, ResultSet rs,
			String columnName) throws SQLException {
		if (maskAttribute != null) {
			return getInteger(rs, columnName);
		}
		return null;
	}

	public Integer getInteger(ResultSet rs, String columnName)
			throws SQLException {
		try {
			if (rs.getObject(columnName) != null) {
				return new Integer(rs.getInt(columnName));
			} else {
				return null;
			}
		} catch (SQLException e) {
			return (Integer) manageException(e);
		}
	}

	public Byte getByte(Object maskAttribute, ResultSet rs, String columnName)
			throws SQLException {
		if (maskAttribute != null) {
			return getByte(rs, columnName);
		}
		return null;
	}

	public Byte getByte(ResultSet rs, String columnName) throws SQLException {
		try {
			if (rs.getObject(columnName) != null) {
				return new Byte(rs.getByte(columnName));
			} else {
				return null;
			}
		} catch (SQLException e) {
			return (Byte) manageException(e);
		}
	}

	public Float getFloat(Object maskAttribute, ResultSet rs, String columnName)
			throws SQLException {
		if (maskAttribute != null) {
			return getFloat(rs, columnName);
		}
		return null;
	}

	public Float getFloat(ResultSet rs, String columnName) throws SQLException {
		try {
			if (rs.getObject(columnName) != null) {
				return new Float(rs.getFloat(columnName));
			} else {
				return null;
			}
		} catch (SQLException e) {
			return (Float) manageException(e);
		}
	}

	public Double getDouble(Object maskAttribute, ResultSet rs,
			String columnName) throws SQLException {
		if (maskAttribute != null) {
			return getDouble(rs, columnName);
		}
		return null;
	}

	public Double getDouble(ResultSet rs, String columnName)
			throws SQLException {
		try {
			if (rs.getObject(columnName) != null) {
				return new Double(rs.getDouble(columnName));
			} else {
				return null;
			}
		} catch (SQLException e) {
			return (Double) manageException(e);
		}
	}

	public Short getShort(Object maskAttribute, ResultSet rs, String columnName)
			throws SQLException {
		if (maskAttribute != null) {
			return getShort(rs, columnName);
		}
		return null;
	}

	public Short getShort(ResultSet rs, String columnName) throws SQLException {
		try {
			if (rs.getObject(columnName) != null) {
				return new Short(rs.getShort(columnName));
			} else {
				return null;
			}
		} catch (SQLException e) {
			return (Short) manageException(e);
		}
	}

	public Long getLong(Object maskAttribute, ResultSet rs, String columnName)
			throws SQLException {
		if (maskAttribute != null) {
			return getLong(rs, columnName);
		}
		return null;
	}

	public Long getLong(ResultSet rs, String columnName) throws SQLException {
		try {
			if (rs.getObject(columnName) != null) {
				return new Long(rs.getLong(columnName));
			} else {
				return null;
			}
		} catch (SQLException e) {
			return (Long) manageException(e);
		}
	}

	public Timestamp getTimestamp(Object maskAttribute, ResultSet rs,
			String columnName) throws SQLException {
		if (maskAttribute != null) {
			return getTimestamp(rs, columnName);
		}
		return null;
	}

	public Timestamp getTimestamp(ResultSet rs, String columnName)
			throws SQLException {
		try {
			return rs.getTimestamp(columnName);
		} catch (SQLException e) {
			return (Timestamp) manageException(e);
		}
	}

	private Object manageException(SQLException e) throws SQLException {
		if (raiseExceptionOnMissingColumnFlag) {
			throw e;
		} else {
			return null;
		}
	}

}
