package sac.pessoa.fisica.jdbc;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.sql.SQLException;
import java.util.List;
import java.util.Hashtable;
import java.util.Map;
import java.util.ArrayList;



import sac.exception.ItemNaoCadastradoException;
import sac.pessoa.fisica.RepositorioTipoServico;
import sac.pessoa.util.jdbc.DBRepository_Abstract;
import sac.pessoa.util.jdbc.PersistenteFactory;
import sac.pessoa.util.jdbc.PersistenteFactory_OID;
import sac.persistencia.CacheObjetos;
import sac.persistencia.OID;
import sac.persistencia.OIDFactory;
import sac.persistencia.PersistenceException;
import sac.persistencia.PoolConexoes;

public class DBTipoServico extends DBRepository_Abstract
    implements RepositorioTipoServico{

    // instancia unica do repositorio
    private static DBTipoServico instancia;

    //Atributos para controle de acesso ao BD.
    private PoolConexoes pool;
    private CacheObjetos cache;
    private OIDFactory oidfactory;

    private PersistenteFactory servicefactory;

    private final String preparedSelectTypeServiceSql =
        "select nm_tipo_servico from tipo_servico where cd_tipo_servico  = ? ";
    private final String preparedSelectServiceIdSql =
        "select cd_tipo_servico as id from tipo_servico where nm_tipo_servico  = ? ";
    private final String preparedInsertTipoServicoSql =
        "insert into tipo_servico (cd_tipo_servico , nm_tipo_servico) " +
		"values (?, ?)";

    private List cache_servicos;

    public DBTipoServico()  throws PersistenceException {
        pool = PoolConexoes.getInstancia();
        cache = CacheObjetos.getInstancia();
        oidfactory = OIDFactory.getInstancia();

        servicefactory =  PersistenteFactory_TipoServico.getInstancia();

        cache_servicos = new ArrayList();
    }

    public static synchronized DBTipoServico getInstancia()
        throws PersistenceException {
        if (instancia == null) {
            instancia = new DBTipoServico();
        }
        return instancia;
    }

    /**
    * Assinatura de método para conlsuta de um tipo de servico
    *
    * @param id            Long contendo ID do tipo de servico.
    *
    * @return String que representa o nome do tipo de servico.
    */
    public String procurar (OID oid )  throws PersistenceException,
        ItemNaoCadastradoException{

        String tipo_servico;
        Connection con = getConnection();
        PreparedStatement pre = createPreparedStatement(con,
            preparedSelectTypeServiceSql);
        try {
            pre.setLong(1, oid.getLongValue());
            tipo_servico = (String) selectObject( oid, pre, servicefactory) ;
            if (tipo_servico != null){
                return tipo_servico;
            } else {
                throw new ItemNaoCadastradoException ("Tipo de servico com "+
                    "codigo = "+oid.getLongValue()+" inexistente." );
            }
        } catch (SQLException sqle){
            throw new PersistenceException ("Problemas no BD.", sqle);
        } finally {
            closeStatement(pre);
            freeConnection(con);
        }
    }

    public OID procurarOID (String tipoServico) throws PersistenceException,
            ItemNaoCadastradoException{
        Connection con = getConnection();
        PreparedStatement pre = createPreparedStatement(con,
            preparedSelectServiceIdSql);
        try {
            pre.setString(1, tipoServico);
            OID oid = (OID) selectObjectFromBd( pre, getCodeFactory() ) ;
            if (oid == null){
                throw new ItemNaoCadastradoException ("Tipo Servico =" +
                    tipoServico+" inexistente." );
            } else {
                return oid;
            }
        } catch (SQLException sqle){
            throw new PersistenceException ("Problemas no BD.", sqle);
        } finally {
            closeStatement(pre);
            freeConnection(con);
        }

    }

   /**
   * Funcao para adicionar Tipo de Servico de Pessoa Fisica
   * executada por um usuário operadoe que extende de
   * pessoa fisica.
   *
   * @param categoria	String contendo categoria a ser cadastrada
   */
    public void inserir(String tipoServico) throws PersistenceException {
        try {
             procurarOID(tipoServico);
        } catch ( ItemNaoCadastradoException iteme){
          Connection con = getConnection();
          PreparedStatement pre = createPreparedStatement(con,
            preparedInsertTipoServicoSql);
          try {
              OID oid = oidfactory.novoOID();
              long idServico = oid.getLongValue();
              pre.setLong(1, idServico);
              pre.setString(2, tipoServico);
              if ( pre.executeUpdate() <= 0){
                  con.rollback();
              }
              con.commit();

              cache_servicos.clear();
          } catch (SQLException sqle){
              try {
              con.rollback();
              } catch (Exception ex) {
                  throw new PersistenceException ("Nao foi possivel realizar "+
                    "rollBack. ", ex);
              }
              throw new PersistenceException ("Erro no Banco de Dados. ", sqle);
          } finally {
              closeStatement(pre);
              freeConnection(con);
          }
        }
   }

    public List listarServicos ()  throws PersistenceException {
        List lstResultado;
        if (cache_servicos.size() > 0 ){
            lstResultado =  cache_servicos;
        } else {
            Connection con = getConnection();
            PreparedStatement pre = createPreparedStatement(con,
                "select * from tipo_servico");
            try {
              lstResultado = selectListFromBD(pre, servicefactory);
              cache_servicos = lstResultado;
            } finally {
                closeStatement(pre);
                freeConnection(con);
            }
        }
        return lstResultado;
   }
}