package br.com.centralit.citcorpore.negocio;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import br.com.centralit.citcorpore.bean.CentroResultadoDTO;
import br.com.centralit.citcorpore.bean.CidadesDTO;
import br.com.centralit.citcorpore.bean.DadosBancariosIntegranteDTO;
import br.com.centralit.citcorpore.bean.DespesaViagemDTO;
import br.com.centralit.citcorpore.bean.EmpregadoDTO;
import br.com.centralit.citcorpore.bean.IntegranteViagemDTO;
import br.com.centralit.citcorpore.bean.ParecerDTO;
import br.com.centralit.citcorpore.bean.ProjetoDTO;
import br.com.centralit.citcorpore.bean.RequisicaoViagemDTO;
import br.com.centralit.citcorpore.bean.RoteiroViagemDTO;
import br.com.centralit.citcorpore.bean.SolicitacaoServicoDTO;
import br.com.centralit.citcorpore.bean.UsuarioDTO;
import br.com.centralit.citcorpore.integracao.CentroResultadoDao;
import br.com.centralit.citcorpore.integracao.CidadesDao;
import br.com.centralit.citcorpore.integracao.DadosBancariosIntegranteDAO;
import br.com.centralit.citcorpore.integracao.DespesaViagemDAO;
import br.com.centralit.citcorpore.integracao.EmpregadoDao;
import br.com.centralit.citcorpore.integracao.IntegranteViagemDao;
import br.com.centralit.citcorpore.integracao.ParecerDao;
import br.com.centralit.citcorpore.integracao.ProjetoDao;
import br.com.centralit.citcorpore.integracao.RequisicaoViagemDAO;
import br.com.centralit.citcorpore.integracao.RoteiroViagemDAO;
import br.com.centralit.citcorpore.integracao.SolicitacaoServicoDao;
import br.com.centralit.citcorpore.negocio.alcada.AlcadaRequisicaoViagem;
import br.com.centralit.citcorpore.util.Enumerados;
import br.com.centralit.citcorpore.util.Enumerados.ServiceRequestStatus;
import br.com.centralit.citcorpore.util.Enumerados.SimNao;
import br.com.citframework.dto.IDto;
import br.com.citframework.excecao.LogicException;
import br.com.citframework.excecao.PersistenceException;
import br.com.citframework.excecao.ServiceException;
import br.com.citframework.integracao.CrudDAO;
import br.com.citframework.integracao.TransactionControler;
import br.com.citframework.integracao.TransactionControlerImpl;
import br.com.citframework.util.UtilDatas;
import br.com.citframework.util.UtilStrings;
import br.com.citframework.util.WebUtil;

@SuppressWarnings("unchecked")
public class RequisicaoViagemServiceEjb extends ComplemInfSolicitacaoServicoServiceEjb implements RequisicaoViagemService {

    private RequisicaoViagemDAO dao;

    @Override
    protected RequisicaoViagemDAO getDao() {
        if (dao == null) {
            dao = new RequisicaoViagemDAO();
        }
        return dao;
    }

    @Override
    public IDto deserializaObjeto(final String serialize) throws Exception {
        RequisicaoViagemDTO requisicaoViagemDto = null;

        if (serialize != null) {
            requisicaoViagemDto = (RequisicaoViagemDTO) WebUtil.deserializeObject(RequisicaoViagemDTO.class, serialize);
            if (requisicaoViagemDto != null && requisicaoViagemDto.getIntegranteViagemSerialize() != null) {
                requisicaoViagemDto.setIntegranteViagem(WebUtil.deserializeCollectionFromString(IntegranteViagemDTO.class, requisicaoViagemDto.getIntegranteViagemSerialize()));
            }
        }

        return requisicaoViagemDto;
    }

    @Override
    public void validaCreate(final SolicitacaoServicoDTO solicitacaoServicoDto, final IDto model) throws Exception {
        this.validaAtualizacao(solicitacaoServicoDto, model);

    }

    @Override
    public void validaDelete(final SolicitacaoServicoDTO solicitacaoServicoDto, final IDto model) throws Exception {}

    @Override
    public void validaUpdate(final SolicitacaoServicoDTO solicitacaoServicoDto, final IDto model) throws Exception {
        this.validaAtualizacao(solicitacaoServicoDto, model);
    }

    public void validaAtualizacao(final SolicitacaoServicoDTO solicitacaoServicoDto, final IDto model) throws Exception {
        final RequisicaoViagemDTO requisicaoViagemDto = (RequisicaoViagemDTO) model;
        this.validaObrigatoriedade(requisicaoViagemDto);
        this.validaCentroResultado(requisicaoViagemDto);
        this.validaProjeto(requisicaoViagemDto);
    }

    public void validaObrigatoriedade(final RequisicaoViagemDTO requisicaoViagemDto) throws Exception {
    	if (requisicaoViagemDto.getFinalidade() == null || requisicaoViagemDto.getFinalidade().equalsIgnoreCase("")) {
			throw new LogicException(this.i18nMessage("rh.alertOCampo")+" ["+this.i18nMessage("requisicaoProduto.finalidade")+"] "+this.i18nMessage("rh.alertEObrigatorio")+"!");
		}
    	if (requisicaoViagemDto.getIdCentroCusto() == null) {
            throw new LogicException(this.i18nMessage("rh.alertOCampo") + " [" + this.i18nMessage("centroResultado") + "] " + this.i18nMessage("rh.alertEObrigatorio") + "!");
        }
		if (requisicaoViagemDto.getIdProjeto() == null) {
	        throw new LogicException(this.i18nMessage("rh.alertOCampo") + " [" + this.i18nMessage("lookup.projeto") + "] " + this.i18nMessage("rh.alertEObrigatorio") + "!");
	    }
    	if (requisicaoViagemDto.getIdMotivoViagem() == null) {
			throw new LogicException(this.i18nMessage("rh.alertOCampo")+" ["+this.i18nMessage("requisicaoViagem.justificativa")+"] "+this.i18nMessage("rh.alertEObrigatorio")+"!");
		}
		if (requisicaoViagemDto.getDescricaoMotivo().equalsIgnoreCase("")) {
			throw new LogicException(this.i18nMessage("rh.alertOCampo")+" ["+this.i18nMessage("requisicaoViagem.motivo")+"] "+this.i18nMessage("rh.alertEObrigatorio")+"!");
		}
		if (UtilStrings.nullToVazio(requisicaoViagemDto.getEstado()).equalsIgnoreCase(RequisicaoViagemDTO.AGUARDANDO_PLANEJAMENTO)) {
			if (requisicaoViagemDto.getIntegranteViagem() == null) {
				throw new LogicException(this.i18nMessage("rh.alertOCampo")+" ["+this.i18nMessage("requisicaoViagem.integranteFuncionario")+"] "+this.i18nMessage("rh.alertEObrigatorio")+"!");
			}

		}
    }

    private void validaProjeto(final RequisicaoViagemDTO requisicaoViagemDto) throws Exception {
        ProjetoDTO projetoDto = null;
        if (requisicaoViagemDto.getIdProjeto() != null) {
            projetoDto = new ProjetoDTO();
            projetoDto.setIdProjeto(requisicaoViagemDto.getIdProjeto());
            projetoDto = (ProjetoDTO) new ProjetoDao().restore(projetoDto);
        }

        if (projetoDto.getIdProjetoPai() == null) {
            throw new LogicException(this.i18nMessage("requisicaoViagem.mensagemProjeto"));
        }
    }

    private void validaCentroResultado(final RequisicaoViagemDTO requisicaoViagemDto) throws Exception {
        CentroResultadoDTO centroCustoDto = null;
        if (requisicaoViagemDto.getIdCentroCusto() != null) {
            centroCustoDto = new CentroResultadoDTO();
            centroCustoDto.setIdCentroResultado(requisicaoViagemDto.getIdCentroCusto());
            centroCustoDto = (CentroResultadoDTO) new CentroResultadoDao().restore(centroCustoDto);
        }

        if (centroCustoDto == null || centroCustoDto.getIdCentroResultadoPai() == null || centroCustoDto.getPermiteRequisicaoProduto() == null
                || !centroCustoDto.getPermiteRequisicaoProduto().equalsIgnoreCase("S")) {
            throw new LogicException(this.i18nMessage("requisicaoViagem.mensagemCentroResultado"));
        }
    }

    @Override
    public IDto create(final TransactionControler tc, final SolicitacaoServicoDTO solicitacaoServicoDto, final IDto model) throws Exception {
    	RequisicaoViagemDTO requisicaoViagemDto = (RequisicaoViagemDTO) model;
		requisicaoViagemDto.setEstado(RequisicaoViagemDTO.AGUARDANDO_PLANEJAMENTO);

		SolicitacaoServicoDao solicitacaoServicoDao = new SolicitacaoServicoDao();
		RequisicaoViagemDAO requisicaoViagemDao = getDao();
		IntegranteViagemDao integranteViagemDao = new IntegranteViagemDao();
		RoteiroViagemDAO roteiroViagemDAO = new RoteiroViagemDAO();
		DadosBancariosIntegranteDAO dadosBancariosIntegranteDAO = new DadosBancariosIntegranteDAO();

		validaCreate(solicitacaoServicoDto, model);

		requisicaoViagemDao.setTransactionControler(tc);
		integranteViagemDao.setTransactionControler(tc);
		solicitacaoServicoDao.setTransactionControler(tc);
		roteiroViagemDAO.setTransactionControler(tc);
		dadosBancariosIntegranteDAO.setTransactionControler(tc);

		if (solicitacaoServicoDto.getIdSolicitacaoServico() != null) {
			requisicaoViagemDto.setIdSolicitacaoServico(solicitacaoServicoDto.getIdSolicitacaoServico());
			requisicaoViagemDto.setRemarcacao("N");

			if(requisicaoViagemDto.getDataFimViagem() == null){
				requisicaoViagemDto.setDataFimViagem(requisicaoViagemDto.getDataInicioViagem());
			}

			requisicaoViagemDto = (RequisicaoViagemDTO) requisicaoViagemDao.create(requisicaoViagemDto);
		}

		if (requisicaoViagemDto.getIntegranteViagemSerialize() != null) {
			inserindoIntegranteViagem(solicitacaoServicoDto, requisicaoViagemDto, integranteViagemDao, roteiroViagemDAO, dadosBancariosIntegranteDAO);
		}

		return requisicaoViagemDto;
	}

    /**
	 * release-5.9.0 - RequisicaoViagemServiceEjb.java_(#inserindoIntegranteViagem).
	 *
	 * @since 27/11/2015
	 * @author ibimon.morais
     */
	private void inserindoIntegranteViagem(final SolicitacaoServicoDTO solicitacaoServicoDto, RequisicaoViagemDTO requisicaoViagemDto, IntegranteViagemDao integranteViagemDao,
			RoteiroViagemDAO roteiroViagemDAO, DadosBancariosIntegranteDAO dadosBancariosIntegranteDAO) throws PersistenceException {

		for (IntegranteViagemDTO integranteViagemDto : requisicaoViagemDto.getIntegranteViagem()) {
			//idenficar se existe id para o integrante e realizar o update

			integranteViagemDto.setIdSolicitacaoServico(requisicaoViagemDto.getIdSolicitacaoServico());
			integranteViagemDto.setIdEmpregado(integranteViagemDto.getIdEmpregado());
			integranteViagemDto.setRemarcacao("N");

			if(integranteViagemDto.getIdRespPrestacaoContas() == null || integranteViagemDto.getIdRespPrestacaoContas() == 0){
				integranteViagemDto.setIdRespPrestacaoContas(integranteViagemDto.getIdEmpregado());
			}

			integranteViagemDto.setEstado(RequisicaoViagemDTO.AGUARDANDO_PLANEJAMENTO);
			integranteViagemDto = (IntegranteViagemDTO) integranteViagemDao.create(integranteViagemDto);

			RoteiroViagemDTO roteiroViagemDTO = new RoteiroViagemDTO();

			roteiroViagemDTO.setDataInicio(UtilDatas.getDataAtual());
			roteiroViagemDTO.setIdSolicitacaoServico(solicitacaoServicoDto.getIdSolicitacaoServico());
			roteiroViagemDTO.setIdIntegrante(integranteViagemDto.getIdIntegranteViagem());
			roteiroViagemDTO.setOrigem(integranteViagemDto.getOrigem());
			roteiroViagemDTO.setDestino(integranteViagemDto.getDestino());
			roteiroViagemDTO.setIda(integranteViagemDto.getDataInicio());
			roteiroViagemDTO.setAeroportoOrigem(integranteViagemDto.getAeroportoOrigem());
			roteiroViagemDTO.setAeroportoDestino(integranteViagemDto.getAeroportoDestino());
			roteiroViagemDTO.setHoraInicio(integranteViagemDto.getHoraInicio());
			roteiroViagemDTO.setHoraFim(integranteViagemDto.getHoraFim());
			roteiroViagemDTO.setHoteisPreferenciais(integranteViagemDto.getHoteisPreferenciais());
			roteiroViagemDTO.setVolta(integranteViagemDto.getVolta());

			roteiroViagemDAO.create(roteiroViagemDTO);

			DadosBancariosIntegranteDTO dadosBancariosIntegranteDTO = new DadosBancariosIntegranteDTO();

			dadosBancariosIntegranteDTO.setIdIntegrante(integranteViagemDto.getIdIntegranteViagem());
			dadosBancariosIntegranteDTO.setAgencia(integranteViagemDto.getAgencia());
			dadosBancariosIntegranteDTO.setBanco(integranteViagemDto.getBanco());
			dadosBancariosIntegranteDTO.setConta(integranteViagemDto.getConta());
			dadosBancariosIntegranteDTO.setCpf(integranteViagemDto.getCpf());
			dadosBancariosIntegranteDTO.setOperacao(integranteViagemDto.getOperacao());

			dadosBancariosIntegranteDAO.create(dadosBancariosIntegranteDTO);

		}
	}


    @Override
    public void update(final TransactionControler tc, final SolicitacaoServicoDTO solicitacaoServicoDto, final IDto model) throws Exception {

    	final RequisicaoViagemDTO requisicaoViagemDto = (RequisicaoViagemDTO) model;
        ParecerDTO parecerDto = new ParecerDTO();

        final ParecerDao parecerDao = new ParecerDao();
        final RequisicaoViagemDAO requisicaoViagemDao = this.getDao();
        final IntegranteViagemDao integranteViagemDao = new IntegranteViagemDao();
        RoteiroViagemDAO roteiroViagemDAO = new RoteiroViagemDAO();
        DadosBancariosIntegranteDAO dadosBancariosIntegranteDAO = new DadosBancariosIntegranteDAO();

        parecerDao.setTransactionControler(tc);
        requisicaoViagemDao.setTransactionControler(tc);
        integranteViagemDao.setTransactionControler(tc);
        roteiroViagemDAO.setTransactionControler(tc);
		dadosBancariosIntegranteDAO.setTransactionControler(tc);

        final RequisicaoViagemDTO bean = (RequisicaoViagemDTO) model;
        if (bean != null) {
	        if (bean.getCancelarRequisicao() == null) {
	        	bean.setCancelarRequisicao("N");
	        }
			if (ServiceRequestStatus.CANCELED.getId().equals(solicitacaoServicoDto.getIdStatus()) && SimNao.NAO.getValorStr().equalsIgnoreCase(bean.getCancelarRequisicao())) {
	        	bean.setCancelarRequisicao("S");
	        }
	        if (bean.getCancelarRequisicao().equalsIgnoreCase("S")) {
				// Cancela aprovação de alçada
	        	this.cancelaAprovacao(solicitacaoServicoDto, tc);

				solicitacaoServicoDto.setIdStatus(ServiceRequestStatus.CANCELED.getId());
	            requisicaoViagemDao.updateNotNull(bean);
	            return;
	        }
        }

        verificaUsuarioComPermissaoParaAlterarRequisicaoViagem(solicitacaoServicoDto);

        this.validaUpdate(solicitacaoServicoDto, model);
        requisicaoViagemDto.setEstado(RequisicaoViagemDTO.AGUARDANDO_PLANEJAMENTO);

        parecerDto = criarUmParecerParaAlteracaoDeRequisicaoViagem(solicitacaoServicoDto, requisicaoViagemDto, parecerDto, parecerDao);

        if (parecerDto != null) {
            requisicaoViagemDto.setIdAprovacao(parecerDto.getIdParecer());
            if (requisicaoViagemDto.getRemarcacao() == null || requisicaoViagemDto.getRemarcacao().trim().equals("")) {
                requisicaoViagemDto.setRemarcacao("N");
            }

            requisicaoViagemDao.updateNotNull(requisicaoViagemDto);
        }

        if (requisicaoViagemDto.getIntegranteViagemSerialize() != null) {
            for (final IntegranteViagemDTO integranteViagemDto : requisicaoViagemDto.getIntegranteViagem()) {

                integranteViagemDto.setIdSolicitacaoServico(requisicaoViagemDto.getIdSolicitacaoServico());
                integranteViagemDto.setIdEmpregado(integranteViagemDto.getIdEmpregado());

                if (integranteViagemDto.getIntegranteFuncionario().equals("S")) {
                    if (!integranteViagemDao.verificarSeIntegranteViagemExiste(integranteViagemDto.getIdSolicitacaoServico(), integranteViagemDto.getIdEmpregado())) {
                        integranteViagemDto.setEstado(RequisicaoViagemDTO.AGUARDANDO_PLANEJAMENTO);
                        integranteViagemDao.create(integranteViagemDto);
                    }
                }
            }
        }
    }

    @SuppressWarnings("rawtypes")
	@Override
    public void update(final IDto model) throws ServiceException {
        // Instancia Objeto controlador de transacao
        final CrudDAO crudDao = this.getDao();
        TransactionControler tc = null;

        try {

            tc = this.getDao().getTransactionControler();

            // Faz validacao, caso exista.
            this.validaUpdate(model);

            // Seta o TransactionController para os DAOs
            crudDao.setTransactionControler(tc);

            // Executa operacoes pertinentes ao negocio.
            crudDao.update(model);

        } catch (final Exception e) {
            e.printStackTrace();
        }
    }

    private void cancelaAprovacao(final SolicitacaoServicoDTO solicitacaoServicoDto, TransactionControler tc) throws Exception {
		new AlcadaRequisicaoViagem().cancelaAprovacao( solicitacaoServicoDto.getIdSolicitacaoServico(), tc);
    }

    /**
	 * TODO Este metodo esta em desuso, pode ser removido na proxima versão
	 */
    public void atualizarRemarcacaoDeViagem(final TransactionControler tc, final SolicitacaoServicoDTO solicitacaoServicoDto, final IDto model) throws Exception {

        final RequisicaoViagemDTO requisicaoViagemDto = (RequisicaoViagemDTO) model;

        ParecerDTO parecerDto = new ParecerDTO();
        final ParecerDao parecerDao = new ParecerDao();
        final RequisicaoViagemDAO requisicaoViagemDao = this.getDao();
        final IntegranteViagemDao integranteViagemDao = new IntegranteViagemDao();

        this.validaUpdate(solicitacaoServicoDto, model);

        parecerDao.setTransactionControler(tc);
        requisicaoViagemDao.setTransactionControler(tc);
        integranteViagemDao.setTransactionControler(tc);

        requisicaoViagemDto.setEstado(RequisicaoViagemDTO.REMARCADO);

        parecerDto.setIdJustificativa(requisicaoViagemDto.getIdJustificativaAutorizacao());
        parecerDto.setIdResponsavel(solicitacaoServicoDto.getUsuarioDto().getIdEmpregado());
        parecerDto.setObservacoes(requisicaoViagemDto.getObservacoes());
        parecerDto.setComplementoJustificativa(requisicaoViagemDto.getComplemJustificativaAutorizacao());
        parecerDto.setAprovado(requisicaoViagemDto.getAutorizado());
        parecerDto.setDataHoraParecer(UtilDatas.getDataHoraAtual());

        parecerDto = (ParecerDTO) parecerDao.create(parecerDto);

        if (parecerDto != null) {
            requisicaoViagemDto.setIdAprovacao(parecerDto.getIdParecer());
            requisicaoViagemDao.updateNotNull(requisicaoViagemDto);
        }

        if (requisicaoViagemDto.getIntegranteViagemSerialize() != null) {
            for (final IntegranteViagemDTO integranteViagemDto : requisicaoViagemDto.getIntegranteViagem()) {

                integranteViagemDto.setIdSolicitacaoServico(requisicaoViagemDto.getIdSolicitacaoServico());
                integranteViagemDto.setIdEmpregado(integranteViagemDto.getIdEmpregado());

                if (integranteViagemDto.getIntegranteFuncionario().equals("S")) {
                    if (!integranteViagemDao.verificarSeIntegranteViagemExiste(integranteViagemDto.getIdSolicitacaoServico(), integranteViagemDto.getIdEmpregado())) {
                        integranteViagemDao.create(integranteViagemDto);
                    }
                }

            }
        }

    }

    @Override
    public void delete(final TransactionControler tc, final SolicitacaoServicoDTO solicitacaoServicoDto, final IDto model) throws Exception {

    }

    /**
	 * Retorna uma coleção com todos os integrantes adicionados em uma solicitação de viagem.
	 *
	 * @param idSolicitacaoServico
	 * @return
	 * @throws Exception
	 */
    @Override
    public Collection<IntegranteViagemDTO> recuperaIntegrantesViagemBySolicitacao(final Integer idSolicitacao) throws Exception {

    	Collection<IntegranteViagemDTO> colIntegrantesViagem = new ArrayList<IntegranteViagemDTO>();

        IntegranteViagemDao integranteDao = new IntegranteViagemDao();
        DadosBancariosIntegranteDAO dadosBancariosIntegranteDAO = new DadosBancariosIntegranteDAO();
        EmpregadoDao empregadoDao = new EmpregadoDao();
        CidadesDao cidadeDAO = new CidadesDao();

        EmpregadoDTO empregado;
        DadosBancariosIntegranteDTO dadosbancarios;
        CidadesDTO cidadeDTO;

        final Collection<IntegranteViagemDTO> colIntegrantAux = integranteDao.findAllByIdSolicitacao(idSolicitacao);
        RoteiroViagemDAO roteiroViagemDAO = new RoteiroViagemDAO();

        if (colIntegrantAux != null) {
            for (final IntegranteViagemDTO integrante : colIntegrantAux) {

            	RoteiroViagemDTO roteiroViagem = roteiroViagemDAO.findByIdIntegrante(integrante.getIdIntegranteViagem());

            	integrante.setDataInicio(roteiroViagem.getDataInicio());
            	integrante.setDataFim(roteiroViagem.getDataFim());
            	integrante.setOrigem(roteiroViagem.getOrigem());
            	integrante.setDestino(roteiroViagem.getDestino());
            	integrante.setAeroportoDestino(roteiroViagem.getAeroportoDestino());
            	integrante.setAeroportoOrigem(roteiroViagem.getAeroportoOrigem());
            	integrante.setIda(roteiroViagem.getIda());
            	integrante.setHoraInicio(roteiroViagem.getHoraInicio());
            	integrante.setVolta(roteiroViagem.getVolta());
            	integrante.setHoraFim(roteiroViagem.getHoraFim());
            	integrante.setHoteisPreferenciais(roteiroViagem.getHoteisPreferenciais());

            	//Nome da cidade origem
            	cidadeDTO = cidadeDAO.findByIdCidade(integrante.getOrigem());
            	if(cidadeDTO != null) {
					integrante.setNomeOrigem(cidadeDTO.getNomeCidade() + " - " + cidadeDTO.getNomeUf());
				}

            	//Nome da cidade destino
            	cidadeDTO = cidadeDAO.findByIdCidade(integrante.getDestino());
            	if(cidadeDTO != null) {
					integrante.setNomeDestino(cidadeDTO.getNomeCidade() + " - " + cidadeDTO.getNomeUf());
				}

                empregado = empregadoDao.restoreByIdEmpregado(integrante.getIdEmpregado());
                integrante.setNome(empregado.getNome());
                integrante.setEmail(empregado.getEmail());
                if (integrante.getIdRespPrestacaoContas() == null) {
                    integrante.setRespPrestacaoContas(empregado.getNome());
                } else {
                    integrante.setRespPrestacaoContas(this.recuperarNome(integrante.getIdRespPrestacaoContas()));
                }


                //Dados bancarios do integrante
                dadosbancarios = dadosBancariosIntegranteDAO.findByIdIntegrante(integrante.getIdIntegranteViagem());
                if(dadosbancarios != null){
                	integrante.setAgencia(dadosbancarios.getAgencia());
                	integrante.setBanco(dadosbancarios.getBanco());
                	integrante.setConta(dadosbancarios.getConta());
                	integrante.setCpf(dadosbancarios.getCpf());
                	integrante.setOperacao(dadosbancarios.getOperacao());
                }

                colIntegrantesViagem.add(integrante);
            }
        }
        return colIntegrantesViagem;
    }

    public String recuperarNome(final Integer idEmpregado) throws Exception {
        final EmpregadoDao dao = new EmpregadoDao();
        EmpregadoDTO empregadoDto = new EmpregadoDTO();

        empregadoDto = dao.restoreByIdEmpregado(idEmpregado);

        return empregadoDto.getNome();
    }

    @Override
    public RequisicaoViagemDTO recuperaRequisicaoPelaSolicitacao(final Integer idSolicitacao) throws Exception {
        return this.getDao().findByIdSolicitacao(idSolicitacao);
    }

    @Override
    public String getResponsaveisEtapaAtualRequisicao(Integer idSolicitacaoServico, String etapa) throws Exception {
    	return this.getDao().getResponsaveisEtapaAtualRequisicao(idSolicitacaoServico, etapa);
    }

    /**
     * Metodo responsavel por controlar os integrantes de uma solicitacao de servico de viajem.
     * @see 27/11/2015
     * @author ibimon.morais
     */
    @Override
	public void tratarIntegranteSolicitacaoViagem(final RequisicaoViagemDTO requisicaoViagemDTO, final List<String> idsParaExclusao, final UsuarioDTO usuario) throws Exception{

    	if(requisicaoViagemDTO == null){
    		return;
    	}

    	TransactionControler transactionControler = new TransactionControlerImpl(this.getDao().getAliasDB());

    	transactionControler.start();

    	final IntegranteViagemDao integranteViagemDao = new IntegranteViagemDao();
    	final DadosBancariosIntegranteDAO dadosBancariosIntegranteDAO = new DadosBancariosIntegranteDAO();
    	RoteiroViagemDAO roteiroViagemDAO = new RoteiroViagemDAO();
    	DespesaViagemDAO despesaViagemDAO = new DespesaViagemDAO();
    	SolicitacaoServicoDao solicitacaoServicoDao = new SolicitacaoServicoDao();
    	try {
    		//Iniciando a transacao
    		dadosBancariosIntegranteDAO.setTransactionControler(transactionControler);
	    	integranteViagemDao.setTransactionControler(transactionControler);
	    	roteiroViagemDAO.setTransactionControler(transactionControler);
			despesaViagemDAO.setTransactionControler(transactionControler);
			solicitacaoServicoDao.setTransactionControler(transactionControler);
			//Inserindo um integrante
			SolicitacaoServicoDTO solicitacaoServicoDto = new SolicitacaoServicoDTO();
			solicitacaoServicoDto = solicitacaoServicoDao.restoreAll(requisicaoViagemDTO.getIdSolicitacaoServico());
			requisicaoViagemDTO.setIntegranteViagem(WebUtil.deserializeCollectionFromString(IntegranteViagemDTO.class, requisicaoViagemDTO.getIntegranteViagemSerialize()));
			// Setando o user na solicitacao para verificação de alteração
			solicitacaoServicoDto.setUsuarioDto(usuario);
			//Fazendo update na requisicao viagem
			updateRequisicaoSemIntegrantes(transactionControler, solicitacaoServicoDto, requisicaoViagemDTO);
			//Trata o integrante para insercao ou alteracao
            definirIntegranteParaAcaoSalvar(requisicaoViagemDTO, transactionControler, integranteViagemDao, solicitacaoServicoDto);
			// Tratar Exclusão
	    	this.tratarExclusaoIntegrante(requisicaoViagemDTO, idsParaExclusao, integranteViagemDao, roteiroViagemDAO, despesaViagemDAO);
	    	// Comitando a transacao
			transactionControler.commit();
    	} catch (final PersistenceException e) {
			e.printStackTrace();
			this.rollbackTransaction(transactionControler, e);
			transactionControler.close();
		}
    }

	private void definirIntegranteParaAcaoSalvar(final RequisicaoViagemDTO requisicaoViagemDTO, final TransactionControler transactionControler, final IntegranteViagemDao integranteViagemDao,
			SolicitacaoServicoDTO solicitacaoServicoDto) throws PersistenceException, Exception {

		for (IntegranteViagemDTO integranteViagemDto : requisicaoViagemDTO.getIntegranteViagem()) {

		    integranteViagemDto.setIdSolicitacaoServico(requisicaoViagemDTO.getIdSolicitacaoServico());
		    integranteViagemDto.setIdEmpregado(integranteViagemDto.getIdEmpregado());
		    integranteViagemDto.setEstado(RequisicaoViagemDTO.AGUARDANDO_PLANEJAMENTO);

		    if (integranteViagemDao.verificarSeIntegranteViagemExiste(integranteViagemDto.getIdSolicitacaoServico(), integranteViagemDto.getIdEmpregado())) {
				salvarIntegrante(transactionControler, requisicaoViagemDTO, solicitacaoServicoDto, integranteViagemDto, false);
		    }else{
		    	salvarIntegrante(transactionControler, requisicaoViagemDTO, solicitacaoServicoDto, integranteViagemDto, true);
		    }

		}
	}

    private void updateRequisicaoSemIntegrantes(final TransactionControler tc, final SolicitacaoServicoDTO solicitacaoServicoDto, final IDto model) throws Exception {
    	final RequisicaoViagemDTO requisicaoViagemDto = (RequisicaoViagemDTO) model;
        ParecerDTO parecerDto = new ParecerDTO();

        final ParecerDao parecerDao = new ParecerDao();
        final RequisicaoViagemDAO requisicaoViagemDao = this.getDao();
        final IntegranteViagemDao integranteViagemDao = new IntegranteViagemDao();
        RoteiroViagemDAO roteiroViagemDAO = new RoteiroViagemDAO();
        DadosBancariosIntegranteDAO dadosBancariosIntegranteDAO = new DadosBancariosIntegranteDAO();

        parecerDao.setTransactionControler(tc);
        requisicaoViagemDao.setTransactionControler(tc);
        integranteViagemDao.setTransactionControler(tc);
        roteiroViagemDAO.setTransactionControler(tc);
		dadosBancariosIntegranteDAO.setTransactionControler(tc);

        final RequisicaoViagemDTO bean = (RequisicaoViagemDTO) model;
        if (bean != null) {
	        if (bean.getCancelarRequisicao() == null) {
	        	bean.setCancelarRequisicao("N");
	        }
			if (ServiceRequestStatus.CANCELED.getId().equals(solicitacaoServicoDto.getIdStatus()) && SimNao.NAO.getValorStr().equalsIgnoreCase(bean.getCancelarRequisicao())) {
	        	bean.setCancelarRequisicao("S");
	        }
	        if (bean.getCancelarRequisicao().equalsIgnoreCase("S")) {
				// Cancela aprovação de alçada
	        	this.cancelaAprovacao(solicitacaoServicoDto, tc);

				solicitacaoServicoDto.setIdStatus(Enumerados.ServiceRequestStatus.CANCELED.getId());
	            requisicaoViagemDao.updateNotNull(bean);
	            return;
	        }
        }
		// Verifica se o usuario que esta alterando é diferente do que criou a requisição
        verificaUsuarioComPermissaoParaAlterarRequisicaoViagem(solicitacaoServicoDto);
		// Valida os campos obrigatorios na atualização
        this.validaUpdate(solicitacaoServicoDto, model);
        requisicaoViagemDto.setEstado(RequisicaoViagemDTO.AGUARDANDO_PLANEJAMENTO);
        //Criando um parecer
        parecerDto = criarUmParecerParaAlteracaoDeRequisicaoViagem(solicitacaoServicoDto, requisicaoViagemDto, parecerDto, parecerDao);

        if (parecerDto != null) {
            requisicaoViagemDto.setIdAprovacao(parecerDto.getIdParecer());
            if (requisicaoViagemDto.getRemarcacao() == null || requisicaoViagemDto.getRemarcacao().trim().equals("")) {
                requisicaoViagemDto.setRemarcacao("N");
            }
            requisicaoViagemDao.updateNotNull(requisicaoViagemDto);
        }
    }

	private void salvarIntegrante(final TransactionControler transactionControler, final RequisicaoViagemDTO requisicaoViagemDTO, SolicitacaoServicoDTO solicitacaoServicoDto,

		IntegranteViagemDTO integranteViagemDto, final boolean acao) throws Exception {
		RoteiroViagemDTO roteiroViagemDTO = new RoteiroViagemDTO();
		DadosBancariosIntegranteDTO dadosBancariosIntegranteDTO = new DadosBancariosIntegranteDTO();
		RoteiroViagemDAO roteiroViagemDAO = new RoteiroViagemDAO();
		final DadosBancariosIntegranteDAO dadosBancariosIntegranteDAO = new DadosBancariosIntegranteDAO();
	    final IntegranteViagemDao integranteViagemDao = new IntegranteViagemDao();
		// Iniciando a transacao
		dadosBancariosIntegranteDAO.setTransactionControler(transactionControler);
		roteiroViagemDAO.setTransactionControler(transactionControler);
		integranteViagemDao.setTransactionControler(transactionControler);

		integranteViagemDto.setIdSolicitacaoServico(requisicaoViagemDTO.getIdSolicitacaoServico());
		integranteViagemDto.setIdEmpregado(integranteViagemDto.getIdEmpregado());
		integranteViagemDto.setRemarcacao("N");

		if (integranteViagemDto.getIdRespPrestacaoContas() == null || integranteViagemDto.getIdRespPrestacaoContas() == 0) {
			integranteViagemDto.setIdRespPrestacaoContas(integranteViagemDto.getIdEmpregado());
		}

		roteiroViagemDTO.setIdSolicitacaoServico(solicitacaoServicoDto.getIdSolicitacaoServico());
		roteiroViagemDTO = roteiroViagemDAO.findByIdIntegrante(integranteViagemDto.getIdIntegranteViagem());

		if(roteiroViagemDTO == null){
			roteiroViagemDTO = new RoteiroViagemDTO();
			roteiroViagemDTO.setIdSolicitacaoServico(solicitacaoServicoDto.getIdSolicitacaoServico());
		}

		if(integranteViagemDto.getIdIntegranteViagem() == null || integranteViagemDto.getIdIntegranteViagem() <= 0){
			IntegranteViagemDTO integranteViagemAux = integranteViagemDao.findByIdSolicitacaoServicoIdEmpregado(integranteViagemDto.getIdSolicitacaoServico(), integranteViagemDto.getIdEmpregado());

			if(integranteViagemAux != null && integranteViagemAux.getIdIntegranteViagem() != null) {
				integranteViagemDto.setIdIntegranteViagem(integranteViagemAux.getIdIntegranteViagem());
			}

		}

		roteiroViagemDTO.setIdIntegrante(integranteViagemDto.getIdIntegranteViagem());
		roteiroViagemDTO.setIdRoteiroViagem(integranteViagemDto.getIdIntegranteViagem());
		roteiroViagemDTO.setDataInicio(integranteViagemDto.getDataInicio());
		roteiroViagemDTO.setOrigem(integranteViagemDto.getOrigem());
		roteiroViagemDTO.setDestino(integranteViagemDto.getDestino());
		roteiroViagemDTO.setIda(integranteViagemDto.getDataInicio());
		roteiroViagemDTO.setAeroportoOrigem(integranteViagemDto.getAeroportoOrigem());
		roteiroViagemDTO.setAeroportoDestino(integranteViagemDto.getAeroportoDestino());
		roteiroViagemDTO.setHoraInicio(integranteViagemDto.getHoraInicio());
		roteiroViagemDTO.setHoraFim(integranteViagemDto.getHoraFim());
		roteiroViagemDTO.setHoteisPreferenciais(integranteViagemDto.getHoteisPreferenciais());
		roteiroViagemDTO.setVolta(integranteViagemDto.getVolta());

		dadosBancariosIntegranteDTO.setIdIntegrante(integranteViagemDto.getIdIntegranteViagem());
		dadosBancariosIntegranteDTO = dadosBancariosIntegranteDAO.findByIdIntegrante(integranteViagemDto.getIdIntegranteViagem());

		if(dadosBancariosIntegranteDTO == null){
			dadosBancariosIntegranteDTO = new DadosBancariosIntegranteDTO();
			dadosBancariosIntegranteDTO.setIdIntegrante(integranteViagemDto.getIdIntegranteViagem());
		}

		dadosBancariosIntegranteDTO.setAgencia(integranteViagemDto.getAgencia());
		dadosBancariosIntegranteDTO.setBanco(integranteViagemDto.getBanco());
		dadosBancariosIntegranteDTO.setConta(integranteViagemDto.getConta());
		dadosBancariosIntegranteDTO.setCpf(integranteViagemDto.getCpf());
		dadosBancariosIntegranteDTO.setOperacao(integranteViagemDto.getOperacao());

		if(!acao){

		    integranteViagemDao.update(integranteViagemDto);
		    roteiroViagemDAO.update(roteiroViagemDTO);
		    if(dadosBancariosIntegranteDTO != null && dadosBancariosIntegranteDTO.getIdDadosBancarios() != null){
		    	dadosBancariosIntegranteDAO.update(dadosBancariosIntegranteDTO);
		    }else{
		    	dadosBancariosIntegranteDAO.create(dadosBancariosIntegranteDTO);
		    }
		}else{
			integranteViagemDto = (IntegranteViagemDTO) integranteViagemDao.create(integranteViagemDto);

			roteiroViagemDTO.setIdIntegrante(integranteViagemDto.getIdIntegranteViagem());
			roteiroViagemDAO.create(roteiroViagemDTO);

			dadosBancariosIntegranteDTO.setIdIntegrante(integranteViagemDto.getIdIntegranteViagem());
			dadosBancariosIntegranteDAO.create(dadosBancariosIntegranteDTO);
		}
	}

	private void tratarExclusaoIntegrante(final RequisicaoViagemDTO iDto, final List<String> idsParaExclusao, final IntegranteViagemDao integranteViagemDao,
			RoteiroViagemDAO roteiroViagemDAO, DespesaViagemDAO despesaViagemDAO) throws PersistenceException {

		if(idsParaExclusao == null || idsParaExclusao.isEmpty()){
			return;
		}

		for(String idParaExclusao : idsParaExclusao){

			//Obtendo o roteiro
			RoteiroViagemDTO roteiroViagemDTO = roteiroViagemDAO.findByIdIntegrante(Integer.valueOf(idParaExclusao));

			if(roteiroViagemDTO != null){

				Collection<DespesaViagemDTO> despesasPorRoteiro = despesaViagemDAO.findDespesaViagemByIdRoteiro(roteiroViagemDTO.getIdRoteiroViagem());

				if(despesasPorRoteiro != null){
					for(DespesaViagemDTO despesa : despesasPorRoteiro){
						despesaViagemDAO.delete(despesa);
					}
				}

				roteiroViagemDAO.delete(roteiroViagemDTO);
			}

			IntegranteViagemDTO integranteViagemDTO = integranteViagemDao.findById(Integer.valueOf(idParaExclusao));

			if(integranteViagemDTO != null) {
				integranteViagemDao.delete(integranteViagemDTO);
			}

		}
	}

	private ParecerDTO criarUmParecerParaAlteracaoDeRequisicaoViagem(final SolicitacaoServicoDTO solicitacaoServicoDto, final RequisicaoViagemDTO requisicaoViagemDto,
			ParecerDTO parecerDto, final ParecerDao parecerDao) throws PersistenceException {
		parecerDto.setIdJustificativa(requisicaoViagemDto.getIdJustificativaAutorizacao());
        parecerDto.setIdResponsavel(solicitacaoServicoDto.getUsuarioDto().getIdEmpregado());
        parecerDto.setObservacoes(requisicaoViagemDto.getObservacoes());
        parecerDto.setComplementoJustificativa(requisicaoViagemDto.getComplemJustificativaAutorizacao());
        parecerDto.setAprovado(requisicaoViagemDto.getAutorizado() == null ? "N" : requisicaoViagemDto.getAutorizado());
        parecerDto.setDataHoraParecer(UtilDatas.getDataHoraAtual());

        parecerDto = (ParecerDTO) parecerDao.create(parecerDto);
		return parecerDto;
	}

	private void verificaUsuarioComPermissaoParaAlterarRequisicaoViagem(final SolicitacaoServicoDTO solicitacaoServicoDto) throws LogicException {
		if (solicitacaoServicoDto.getIdSolicitante().intValue() == solicitacaoServicoDto.getUsuarioDto().getIdEmpregado().intValue()
				&& !ServiceRequestStatus.CANCELED.getId().equals(solicitacaoServicoDto.getIdStatus())) {
			throw new LogicException("Usuário sem permissão para Execução!");
        }
	}
}
