package br.com.centralit.citcorpore.negocio;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.sql.Date;
import java.util.Collection;
import java.util.Iterator;

import br.com.centralit.citcorpore.bean.ExecucaoAtividadePeriodicaDTO;
import br.com.centralit.citcorpore.bean.UploadDTO;
import br.com.centralit.citcorpore.integracao.AnexoDao;
import br.com.centralit.citcorpore.integracao.ExecucaoAtividadePeriodicaDao;
import br.com.centralit.citcorpore.util.CriptoUtils;
import br.com.centralit.citcorpore.util.Enumerados;
import br.com.centralit.citcorpore.util.ParametroUtil;
import br.com.centralit.citcorpore.util.Util;
import br.com.centralit.citged.bean.ControleGEDDTO;
import br.com.centralit.citged.integracao.ControleGEDDao;
import br.com.centralit.citged.negocio.ControleGEDService;
import br.com.citframework.dto.IDto;
import br.com.citframework.excecao.LogicException;
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.service.CrudServiceImpl;
import br.com.citframework.service.ServiceLocator;
import br.com.citframework.util.Constantes;
import br.com.citframework.util.UtilDatas;
import br.com.citframework.util.UtilStrings;

@SuppressWarnings({ "rawtypes", "unchecked" })
public class ExecucaoAtividadePeriodicaServiceEjb extends CrudServiceImpl implements ExecucaoAtividadePeriodicaService {

	private ExecucaoAtividadePeriodicaDao dao;
	protected ControleGEDDao controleGEDDao = new ControleGEDDao();

	@Override
	protected ExecucaoAtividadePeriodicaDao getDao() {
		if (this.dao == null) {
			this.dao = new ExecucaoAtividadePeriodicaDao();
		}
		return this.dao;
	}

	@Override
	protected void validaCreate(final Object arg0) throws Exception {
		final ExecucaoAtividadePeriodicaDTO execucaoAtividadePeriodicaDto = (ExecucaoAtividadePeriodicaDTO) arg0;
		if (!execucaoAtividadePeriodicaDto.getSituacao().equals("S")) {
			execucaoAtividadePeriodicaDto.setIdMotivoSuspensao(null);
			execucaoAtividadePeriodicaDto.setComplementoMotivoSuspensao(null);
		}
	}

	@Override
	protected void validaUpdate(final Object arg0) throws Exception {
		this.validaCreate(arg0);
	}

	@Override
	public Collection findByIdAtividadePeriodica(final Integer idAtividadePeriodicaParm) throws Exception {
		try {
			return this.getDao().findByIdAtividadePeriodica(idAtividadePeriodicaParm);
		} catch (final Exception e) {
			throw new ServiceException(e);
		}
	}

	@Override
	public void deleteByIdAtividadePeriodica(final Integer parm) throws Exception {
		try {
			this.getDao().deleteByIdAtividadePeriodica(parm);
		} catch (final Exception e) {
			throw new ServiceException(e);
		}
	}

	@Override
	public void deleteByIdEmpregado(final Integer parm) throws Exception {
		try {
			this.getDao().deleteByIdEmpregado(parm);
		} catch (final Exception e) {
			throw new ServiceException(e);
		}
	}

	@Override
	public IDto create(IDto model) throws ServiceException, LogicException {
		// Instancia Objeto controlador de transacao
		final CrudDAO crudDao = this.getDao();
		final AnexoDao anexoDao = new AnexoDao();
		final TransactionControler tc = new TransactionControlerImpl(crudDao.getAliasDB());
		try {
			// Faz validacao, caso exista.
			this.validaCreate(model);

			// Instancia ou obtem os DAOs necessarios.

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

			// Inicia transacao
			tc.start();

			// Executa operacoes pertinentes ao negocio.
			model = crudDao.create(model);
			final ExecucaoAtividadePeriodicaDTO execucaoAtividadeDto = (ExecucaoAtividadePeriodicaDTO) model;

			this.tratarInformacoesDeArquivosGED(execucaoAtividadeDto.getColArquivosUpload(), 1, execucaoAtividadeDto, tc);

			// Faz commit e fecha a transacao.
			tc.commit();

			return model;
		} catch (final Exception e) {
			this.rollbackTransaction(tc, e);
		} finally {
			tc.closeQuietly();
		}
		return model;
	}

	@Override
	public void update(final IDto model) throws ServiceException, LogicException {
		// Instancia Objeto controlador de transacao
		final CrudDAO crudDao = this.getDao();
		final AnexoDao anexoDao = new AnexoDao();
		final TransactionControler tc = new TransactionControlerImpl(crudDao.getAliasDB());
		try {
			// Faz validacao, caso exista.
			this.validaUpdate(model);

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

			// Inicia transacao
			tc.start();

			// Executa operacoes pertinentes ao negocio.
			crudDao.update(model);
			final ExecucaoAtividadePeriodicaDTO execucaoAtividadeDto = (ExecucaoAtividadePeriodicaDTO) model;
			this.tratarInformacoesDeArquivosGED(execucaoAtividadeDto.getColArquivosUpload(), 1, execucaoAtividadeDto, tc);

			// Faz commit e fecha a transacao.
			tc.commit();

		} catch (final Exception e) {
			this.rollbackTransaction(tc, e);
		} finally {
			tc.closeQuietly();
		}
	}

	@Override
	public IDto restore(final IDto model) throws ServiceException, LogicException {
		try {
			final IDto obj = this.getDao().restore(model);
			final ExecucaoAtividadePeriodicaDTO execucaoAtividadeDto = (ExecucaoAtividadePeriodicaDTO) obj;
			final ControleGEDDao controleGedDao = new ControleGEDDao();
			final Collection col = controleGedDao.listByIdTabelaAndID(ControleGEDDTO.TABELA_EXECUCAOATIVIDADE, execucaoAtividadeDto.getIdExecucaoAtividadePeriodica());
			execucaoAtividadeDto.setColArquivosUpload(col);
			return obj;
		} catch (final LogicException e) {
			throw new ServiceException(e);
		} catch (final Exception e) {
			throw new ServiceException(e);
		}
	}

	/**
	 * Faz o tratamento de configuracao e manutencao dos arquivos de upload e validacao dos mesmos.
	 * incidente-186200 - ExecucaoAtividadePeriodicaServiceEjb.java_(#gravarInformacoesGED).
	 *
	 * @since 24/02/2016
	 * @author ibimon.morais
	 */
	private void tratarInformacoesDeArquivosGED(final Collection colArquivosUpload, final int idEmpresa, final ExecucaoAtividadePeriodicaDTO execucaoAtividadeDto,
			final TransactionControler tc) throws Exception {
		String gedDiretorio = ParametroUtil.getValorParametroCitSmartHashMap(Enumerados.ParametroSistema.GedDiretorio, "");
		String gedInterno = ParametroUtil.getValorParametroCitSmartHashMap(Enumerados.ParametroSistema.GedInterno, "S");
		String gedInternoBancoDados = ParametroUtil.getValorParametroCitSmartHashMap(Enumerados.ParametroSistema.GedInternoBD, "N");
		String pasta = "";

		if (gedDiretorio == null || gedDiretorio.trim().equalsIgnoreCase("")) {
			gedDiretorio = "";
		}

		if (gedDiretorio.equalsIgnoreCase("")) {
			gedDiretorio = Constantes.getValue("DIRETORIO_GED");
		}

		if (gedDiretorio == null || gedDiretorio.equalsIgnoreCase("")) {
			gedDiretorio = "/ged";
		}

		if (gedInterno == null) {
			gedInterno = "S";
		}

		if (!UtilStrings.isNotVazio(gedInternoBancoDados)) {
			gedInternoBancoDados = "N";
		}

		final ControleGEDService controleGEDService = (ControleGEDService) ServiceLocator.getInstance().getService(ControleGEDService.class, null);
		deletarArquivos(execucaoAtividadeDto, tc, gedDiretorio, gedInterno, gedInternoBancoDados);
		pasta = this.definirPastaGedInternoDefinido(idEmpresa, gedDiretorio, gedInterno, controleGEDService, pasta);
		if (colArquivosUpload != null && !colArquivosUpload.isEmpty()) {
			this.percorrerArquivosUpload(colArquivosUpload, idEmpresa, execucaoAtividadeDto, gedDiretorio, gedInterno, gedInternoBancoDados, controleGEDService, pasta);
		}
	}

	/**
	 * incidente-186200 - ExecucaoAtividadePeriodicaServiceEjb.java_(#definirPastaGedInternoDefinido).
	 *
	 * @since 24/02/2016
	 * @author ibimon.morais
	 */
	private String definirPastaGedInternoDefinido(final int idEmpresa, final String gedDiretorio, final String gedInterno, final ControleGEDService controleGEDService, String pasta)
			throws Exception {
		if (gedInterno.equalsIgnoreCase("S")) {
			pasta = controleGEDService.getProximaPastaArmazenar();
			File fileDir = new File(gedDiretorio);
			if (!fileDir.exists()) {
				fileDir.mkdirs();
			}
			fileDir = new File(gedDiretorio + "/" + idEmpresa);
			if (!fileDir.exists()) {
				fileDir.mkdirs();
			}
			fileDir = new File(gedDiretorio + "/" + idEmpresa + "/" + pasta);
			if (!fileDir.exists()) {
				fileDir.mkdirs();
			}
		}
		return pasta;
	}

	/**
	 * incidente-186200 - ExecucaoAtividadePeriodicaServiceEjb.java_(#percorrerArquivosUpload).
	 *
	 * @since 24/02/2016
	 * @author ibimon.morais
	 */
	private void percorrerArquivosUpload(final Collection colArquivosUpload, final int idEmpresa, final ExecucaoAtividadePeriodicaDTO execucaoAtividadeDto,
			final String prontuario_ged_diretorio, final String prontuario_ged_interno, final String prontuarioGedInternoBancoDados, final ControleGEDService controleGEDService,
			final String pasta) throws LogicException, ServiceException, FileNotFoundException, IOException, ClassNotFoundException, GeneralSecurityException {
		for (final Iterator it = colArquivosUpload.iterator(); it.hasNext();) {
			final UploadDTO uploadDTO = (UploadDTO) it.next();
			// Se nao for temporario
			if (uploadDTO.getTemporario() != null && !uploadDTO.getTemporario().equalsIgnoreCase("S")) {
				continue;
			}
			ControleGEDDTO controleGEDDTO = this.definirControleGEDDTO(execucaoAtividadeDto, pasta, uploadDTO);
			this.definirGedInterno(prontuario_ged_interno, prontuarioGedInternoBancoDados, uploadDTO, controleGEDDTO);
			controleGEDDTO = controleGEDService.create(controleGEDDTO);
			this.tratarArquivosGEDConfirmados(idEmpresa, prontuario_ged_diretorio, prontuario_ged_interno, prontuarioGedInternoBancoDados, pasta, uploadDTO, controleGEDDTO);
		}
	}

	/**
	 * incidente-186200 - ExecucaoAtividadePeriodicaServiceEjb.java_(#deletarArquivos).
	 *
	 * @since 24/02/2016
	 * @author ibimon.morais
	 */
	private void deletarArquivos(final ExecucaoAtividadePeriodicaDTO iDto, final TransactionControler transacao, final String gedDiretorio, final String gedInterno,
			final String gedInternoBancoDados) throws Exception {
		if (iDto.getColArquivosUploadExcluir() != null && !iDto.getColArquivosUploadExcluir().isEmpty()) {
			this.getControleGEDDao().setTransactionControler(transacao);
			for (final UploadDTO valorId : iDto.getColArquivosUploadExcluir()) {
				if (valorId.getPath().startsWith("ID=")) {
					ControleGEDDTO controleGEDDTO = new ControleGEDDTO();
					controleGEDDTO.setIdControleGED(this.obterIdParaExclusaoGed(valorId.getPath()));
					controleGEDDTO = (ControleGEDDTO) this.getControleGEDDao().restore(controleGEDDTO);
					this.getControleGEDDao().delete(controleGEDDTO);
					final File arquivo = montarArquivoParaDelecaoNoDiretorio(iDto, gedDiretorio, controleGEDDTO);
					this.deleteDir(arquivo);
				} else {
					final File arquTemp = new File(valorId.getPath());
					this.deleteDir(arquTemp);
				}
			}
		}
	}

	/**
	 * br.com.centralit.citcorpore.negocio.CasoNegocioServiceEjb.java_(#deleteDir)
	 *
	 * @since 20/10/2015
	 * @author ibimon.morais
	 */
	public boolean deleteDir(final File dir) {
		if (dir.isDirectory()) {
			final String[] children = dir.list();
			for (final String element : children) {
				final boolean success = this.deleteDir(new File(dir, element));
				if (!success) {
					return false;
				}
			}
		}
		return dir.delete();
	}

	/**
	 * br.com.centralit.citcorpore.negocio.CasoNegocioServiceEjb.java_(#montarArquivoParaDelecaoNoDiretorio)
	 * 
	 * @since 23/10/2015
	 * @author ibimon.morais
	 */
	private File montarArquivoParaDelecaoNoDiretorio(final ExecucaoAtividadePeriodicaDTO iDto, final String gedDiretorio, ControleGEDDTO controleGEDDTO) {
		final File arquivo = new File(gedDiretorio.concat("/").concat(String.valueOf(iDto.getIdEmpresa())).concat("/").concat(controleGEDDTO.getPasta()).concat("/")
				.concat(String.valueOf(controleGEDDTO.getIdControleGED())).concat(".").concat("ged"));
		return arquivo;
	}

	/**
	 * br.com.centralit.citcorpore.negocio.CasoNegocioServiceEjb.java_(#obterIdParaExclusaoGed)
	 *
	 * @since 20/10/2015
	 * @author ibimon.morais
	 */
	private Integer obterIdParaExclusaoGed(final String strParaVerificar) {
		final String[] strParaVerificarArray = strParaVerificar.split("=");
		return Integer.valueOf(strParaVerificarArray[1].toString());
	}

	/**
	 * incidente-186200 - ExecucaoAtividadePeriodicaServiceEjb.java_(#definirControleGEDDTO).
	 *
	 * @since 24/02/2016
	 * @author ibimon.morais
	 * @throws LogicException
	 * @throws ServiceException
	 */
	private ControleGEDDTO definirControleGEDDTO(final ExecucaoAtividadePeriodicaDTO execucaoAtividadeDto, final String pasta, final UploadDTO uploadDTO) throws ServiceException,
			LogicException {
		ControleGEDDTO controleGEDDTO = new ControleGEDDTO();
		controleGEDDTO.setIdTabela(ControleGEDDTO.TABELA_EXECUCAOATIVIDADE);
		controleGEDDTO.setId(execucaoAtividadeDto.getIdExecucaoAtividadePeriodica());
		controleGEDDTO.setDataHora(UtilDatas.getDataAtual());
		controleGEDDTO.setDescricaoArquivo(uploadDTO.getDescricao());
		controleGEDDTO.setExtensaoArquivo(Util.getFileExtension(uploadDTO.getNameFile()));
		controleGEDDTO.setPasta(pasta);
		controleGEDDTO.setNomeArquivo(uploadDTO.getNameFile());
		return controleGEDDTO;
	}

	/**
	 * incidente-186200 - ExecucaoAtividadePeriodicaServiceEjb.java_(#tratarArquivosGEDConfirmados).
	 *
	 * @since 24/02/2016
	 * @author ibimon.morais
	 */
	private void tratarArquivosGEDConfirmados(final int idEmpresa, final String prontuario_ged_diretorio, final String prontuario_ged_interno,
			final String prontuarioGedInternoBancoDados, final String pasta, final UploadDTO uploadDTO, final ControleGEDDTO controleGEDDTO) throws FileNotFoundException,
			IOException, ClassNotFoundException, GeneralSecurityException {
		// Se utiliza GED
		if (prontuario_ged_interno.equalsIgnoreCase("S") && !"S".equalsIgnoreCase(prontuarioGedInternoBancoDados)) {
			if (controleGEDDTO != null) {
				final File arquivo = new File(prontuario_ged_diretorio + "/" + idEmpresa + "/" + pasta + "/" + controleGEDDTO.getIdControleGED() + "."
						+ Util.getFileExtension(uploadDTO.getNameFile()));
				CriptoUtils.encryptFile(uploadDTO.getPath(), prontuario_ged_diretorio + "/" + idEmpresa + "/" + pasta + "/" + controleGEDDTO.getIdControleGED() + ".ged", System
						.getProperties().get("user.dir") + Constantes.getValue("CAMINHO_CHAVE_PUBLICA"));

				arquivo.delete();
			}
		}
	}

	/**
	 * incidente-186200 - ExecucaoAtividadePeriodicaServiceEjb.java_(#definirGedInterno).
	 *
	 * @since 24/02/2016
	 * @author ibimon.morais
	 */
	private void definirGedInterno(final String prontuario_ged_interno, final String prontuarioGedInternoBancoDados, final UploadDTO uploadDTO, final ControleGEDDTO controleGEDDTO) {
		// Se utiliza GED
		if (prontuario_ged_interno.equalsIgnoreCase("S") && "S".equalsIgnoreCase(prontuarioGedInternoBancoDados)) {
			// interno e eh BD
			controleGEDDTO.setPathArquivo(uploadDTO.getPath()); // Isso vai fazer a gravacao no BD. dento
		} else {
			controleGEDDTO.setPathArquivo(null);
		}
	}

	@Override
	public Collection findBlackoutByIdMudancaAndPeriodo(final Integer idMudanca, final Date dataInicio, final Date dataFim) throws Exception {
		return this.getDao().findBlackoutByIdMudancaAndPeriodo(idMudanca, dataInicio, dataFim);
	}

	public ControleGEDDao getControleGEDDao() {
		if (this.controleGEDDao == null) {
			this.controleGEDDao = new ControleGEDDao();
		}
		return this.controleGEDDao;
	}
}
