package com.rjconsultores.ventaboletos.dao.util;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.HibernateException;
/**
 * Classe que trata a geração do ID da tabela Aidf.
 * 
 * Foi abandonado o uso da sequence pois existiam lacunas nos numeros e já havia atingido o tamanho máximo de 3 dígitos, com isso
 * sendo necessário aproveitar os número que não haviam sido utilizados
 * 
 * @author gleimar
 *
 */
public class IdAidfStore {

	private static final Logger log = LogManager.getLogger(IdAidfStore.class);
	
	private static final String LIMITE_ID_AIDF = "LIMITE_ID_AIDF";
	
	private static IdAidfStore INSTANCE = new IdAidfStore();
	
	private int indiceAtual = 1;
	
	private IdAidfStore(){
		
	}
	
	public static IdAidfStore getInstance(){
		return INSTANCE;
	}
	
	/**
	 * Buscar novo limite de aidf.
	 * 
	 * Por padrão é 999. Com o intuito de ativar de forma gradual, foi criado uma constante para essa Função
	 * @param connection
	 * @return
	 */
	private int buscarLimiteAidf(Connection connection){
		int qtdMaxima = 999;
		PreparedStatement ps;
		
		log.info("buscando constante limite aidf ...");
		
		try {
			
			ps = connection.prepareStatement("select VALORCONSTANTE from constante  where NOMBCONSTANTE = :1");
			ps.setString(1, LIMITE_ID_AIDF);
			
			ResultSet rs = ps.executeQuery();
			
			if (rs.next()){
	
				String tmp = rs.getString("VALORCONSTANTE");
				
				if (StringUtils.isNotBlank(tmp)){
					qtdMaxima = Integer.parseInt(tmp);
					
					log.info(String.format("constante encontrada : %s",tmp));
				}
			}else{
				log.info("constante não parametrizada");
			}
			
			rs.close();
			ps.close();
			
		}catch(Throwable e){
			log.error("erro buscar constante",e);
		}
		
		return qtdMaxima;
	}
	
	public synchronized Serializable getNextId(Connection connection) throws HibernateException {

		int qtdMaxima = this.buscarLimiteAidf(connection);
		
		log.info(String.format("qtdMaxima:%s",qtdMaxima));
				
		long idEncontrado = -1;
		
		PreparedStatement ps;
		
		try {
			
			ps = connection.prepareStatement("select count(*) as qtd from aidf where aidf_id = :1");
		
			for(; (idEncontrado == -1) && (indiceAtual <= qtdMaxima);indiceAtual++){	
				ps.setInt(1, indiceAtual);
				ResultSet rs = ps.executeQuery();
				rs.next();
				int qtd = rs.getInt("qtd");
				
				if (qtd == 0){
					idEncontrado = indiceAtual;
				}
			}
			
		} catch (SQLException e) {
			log.error("erro ao buscar id aidf",e);
			throw new HibernateException(e);
		}
		
		log.info("indiceAtual="+indiceAtual);
		log.info("idEncontrado="+idEncontrado);
		
		if (indiceAtual > qtdMaxima && (idEncontrado != qtdMaxima) ){
			throw new HibernateException("A qtd de IDs permitidos para AIDF foi atingido:"+qtdMaxima);
		}
		
		if (idEncontrado == -1){
			throw new HibernateException("Houve algum erro ao buscar um novo ID para AIDF");
		}
		return idEncontrado;
	}

}
