package com.rjconsultores.ventaboletos.utilerias.exportacao.bpe.xml;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.rjconsultores.ventaboletos.constantes.Constantes;
import com.rjconsultores.ventaboletos.utilerias.DateUtil;
import com.rjconsultores.ventaboletos.utilerias.exportacao.bpe.ExportacaoBPEVo;
import com.rjconsultores.ventaboletos.vo.bpe.BPeVO;

import br.inf.portalfiscal.bpe.TBPe;

public class BPeUtil {

	private static final Logger log = LogManager.getLogger(ExportacaoBPEVo.class);

	public static TBPe convertXmlToBpe(String xml) {
		TBPe objeto = null;
		if (xml != null) {
			try {
				JAXBContext jc = JAXBContext.newInstance(TBPe.class);
				Unmarshaller unmarshaller = jc.createUnmarshaller();
				InputStream input = new ByteArrayInputStream(xml.getBytes(Constantes.UTF_8));
				StreamSource source = new StreamSource(input);
				objeto = (TBPe) unmarshaller.unmarshal(source);
			} catch (JAXBException e) {
				log.info("Nao encontrou o xml bpe");
			} catch (UnsupportedEncodingException e) {
				log.info("Nao encontrou o xml bpe");
			}
		}
		return objeto;
	}
	
	public static Map<String, InputStream> convertBPeXmlRegularToArquivoXml(BPeVO bpe) {
		try {
			String complemento = "BPeRecepacao_E";
			String nomeArquivo = getNomeArquivo(bpe, complemento);
			return gerarArquivo(bpe.getXmlEnvio(), nomeArquivo);
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		}
		return null;
	}

	public static Map<String, InputStream> convertBPeXmlRepostaToArquivoXml(BPeVO bpe) {
		try {
			String complemento = "BPeRecepacao_R";
			String nomeArquivo = getNomeArquivo(bpe, complemento);
			return gerarArquivo(bpe.getXmlResposta(), nomeArquivo);
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		}
		return null;
	}
	
	public static Map<String, InputStream> convertBPeXmlRegularEventoToArquivoXml(BPeVO bpe) {
		try {
			String complemento = "BPeRecepacaoEvento_" + bpe.getTipoevento() + "_E";
			String nomeArquivo = getNomeArquivo(bpe, complemento);
			return gerarArquivo(bpe.getXmlEnvio(), nomeArquivo);
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		}
		return null;
	}
	
	public static Map<String, InputStream> convertBPeXmlRepostaEventoToArquivoXml(BPeVO bpe) {
		try {
			String complemento = "BPeRecepacaoEvento_" + bpe.getTipoevento() + "_R";
			String nomeArquivo = getNomeArquivo(bpe, complemento);
			return gerarArquivo(bpe.getXmlResposta(), nomeArquivo);
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		}
		return null;
	}

	private static Map<String, InputStream> gerarArquivo(String xml, String nomeArquivo) throws IOException {
		InputStream file = IOUtils.toInputStream(xml, Constantes.UTF_8);
		Map<String, InputStream> arquivo = new HashMap<String, InputStream>();
		arquivo.put(nomeArquivo, file);
		return arquivo;
	}
	
	private static String getNomeArquivo(BPeVO bpe, String complemento) {
		StringBuilder nomeArquivo = new StringBuilder();
		nomeArquivo.append(DateUtil.getStringDate(bpe.getFechorventa(), "yyyyMMddHHmmss"))
				   .append("_")
				   .append(bpe.getChbpe())
				   .append("_")
				   .append(bpe.getNumserieBpe())
				   .append("_")
				   .append(bpe.getNumBpe())
				   .append("_")
				   .append(complemento)
				   .append(".xml");
		
		return nomeArquivo.toString();
		
	}
	
	public static byte[] zipFiles(Map<String, InputStream> arquivos) {
		
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ZipOutputStream outputStream = new ZipOutputStream(baos);
		InputStream inputStream = null;
		
		try {
			for (Entry<String, InputStream> arquivo : arquivos.entrySet()) {
				outputStream.putNextEntry(new ZipEntry(arquivo.getKey()));
				byte[] readBuff = new byte[4096];
				int readLen = -1;

				while ((readLen = arquivo.getValue().read(readBuff)) != -1) {
					outputStream.write(readBuff, 0, readLen);
				}
				outputStream.closeEntry();
				arquivo.getValue().close();
			}	

			outputStream.finish();

		} catch (Exception e) {
			log.error(e.getMessage(), e);

		} finally {
			if (outputStream != null) {
				try {
					outputStream.close();
				} catch (IOException e) {
					log.error(e.getMessage(), e);
				}
			}

			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					log.error(e.getMessage(), e);
				}
			}
		}

		return baos.toByteArray();
	}

}
