package br.com.bancooriginal.cyberbank.servico.client;

import java.awt.Color;
import java.io.File;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Holder;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.soap.SOAPFaultException;

import net.technisys.cmm.services.errors.v1.Errors;
import net.technisys.cmm.services.metadata.v1.Metadata;
import net.technisys.cmm.services.metadata.v1.Metadata.CustomProperties;
import net.technisys.cmm.services.metadata.v1.Metadata.ExecutingChannel;
import net.technisys.cmm.services.processaccountapply_external_movements_ws.v0.MovementFault;
import net.technisys.cmm.services.processaccountapply_external_movements_ws.v0.ProcessAccountApplyExternalMovementsWS;
import net.technisys.cmm.services.processaccountapply_external_movements_ws.v0.ProcessAccountApplyExternalMovementsWS_Service;
import net.technisys.cmm.services.processaccountapplyexternalmovementsws.rq.v1.MsgMovement;
import net.technisys.cmm.services.processaccountapplyexternalmovementsws.rq.v1.ProcessAccountApplyExternalMovementsWSRequest;
import net.technisys.cmm.services.processaccountapplyexternalmovementsws.rs.v1.Generic.Msg;
import net.technisys.cmm.services.processaccountapplyexternalmovementsws.rs.v1.ProcessAccountApplyExternalMovementsWSResponse;
import br.com.bancooriginal.cyberbank.dto.Lancamento;
import br.com.bancooriginal.cyberbank.dto.Parametrizacao;
import br.com.bancooriginal.cyberbank.exception.CyberBankException;
import br.com.bancooriginal.cyberbank.util.CBUtil;
import br.com.bancooriginal.cyberbank.util.XMLUtil;

/**
 * Classe cliente do servico de lancamento em contas corrente
 * processAccountApply_External_Movements_WS, versao 1.0
 * Esta classe monta o objeto request, chama o servico e trata o retorno.
 * 
 * @author filipe.sa
 *
 */
public class CyberbankClient {
	
	String enderecoServico;

	
	/**
	 * Metodo que realiza o lancamento via Webservice disponibilizado no CMM pelo Cyberbank
	 * @param lancamento
	 * @throws CyberBankException
	 */
	@SuppressWarnings("rawtypes")
	public void lancar(Lancamento lancamento) throws CyberBankException{
		
		try {
			
			//Leitura da parametrizacao do servico
			Parametrizacao parametrizacao = XMLUtil.lerConfiguracoes(new File("parametrizacao.xml"));;
			
			//Criamos o objeto que sera o request da mensagem
			ProcessAccountApplyExternalMovementsWSRequest request = new ProcessAccountApplyExternalMovementsWSRequest();
			
			//criacao de formatador de data no formato esperado pelo servico
			SimpleDateFormat sd = new SimpleDateFormat("yyyyMMddHHMMsshhh");
	    	String data = sd.format(new Date());
			
	    	//Criacao do objeto metadata que sera o header da mensagem
			Metadata metadata = new Metadata();
			
			//Parametros fixos
			metadata.setServiceId("processAccountApply_External_Movements_WS");
			metadata.setServiceVersion("1.0");
			metadata.setServiceContext("ORG");
			
			//parametros provenientes da parametrizacao
			metadata.setSessionId(parametrizacao.getSessionId());
			metadata.setUserId(parametrizacao.getUserId());
			metadata.setExecutingOperatorId(parametrizacao.getUserId());
			metadata.setSourceTime(data);
			metadata.setInstitutionId(parametrizacao.getInstitutionId());
			metadata.setBranchId(parametrizacao.getBranchId());
			metadata.setTerminalId(parametrizacao.getTerminalId());
			metadata.setParityCurrencyId(parametrizacao.getParityCurrencyId());
			metadata.setParityQuotationNemotecnic(parametrizacao.getParityQuotationTypeNemotecnic());
			metadata.setLocalCountryId(parametrizacao.getLocalCountryId());
			metadata.setLocalCurrencyId(parametrizacao.getLocalCurrencyId());
			metadata.setBankId(parametrizacao.getBankId());
			metadata.setSourceDate(data);
			metadata.setSourceTime(data);
			metadata.setMsgTypeId(parametrizacao.getMsgTypeId());
			metadata.setOriginBranchId(parametrizacao.getOriginBranchId());
			metadata.setDependencyId(parametrizacao.getDependencyId());
			metadata.setBusinessDate(lancamento.getDataParaMensagem());
			ExecutingChannel executingChannel = new ExecutingChannel();
			executingChannel.setMnemonic("8");
			metadata.setExecutingChannel(executingChannel);
			CustomProperties custom = new CustomProperties();
			custom.setServiceContext("ORG");
			metadata.setCustomProperties(custom);
	       
			//Criacao de handler que serve para manipular mensagem antes de de ser enviada
			//e, quando recebida, antes de ser manipulada
			List<Handler> handlerChain = new ArrayList<Handler>();
			handlerChain.add(new MensagemHandler());

			//Criacao de holder para o metadata
			Holder<Metadata> holder = new Holder<Metadata>();
			holder.value = metadata;
			
			//Criacao do corpo da mensagem cujos dados sao provenientes
			//da tela de lancamento
			MsgMovement mensagem = new MsgMovement();
			
			//parametros fixos
			mensagem.setName("msgMovement");
			mensagem.setDataModel("product.financials");
			mensagem.setVersion("1.0");
			
//			//Campos obrigatorios
			mensagem.setOperationId(lancamento.getNumConta());
			mensagem.setTxnCodeId(new BigInteger(lancamento.getTransacao()));
			mensagem.setReasonCodeId(new BigInteger(lancamento.getMotivo()));
			mensagem.setValuedDate(lancamento.getDataParaMensagem());
			mensagem.setAmount(new Double(lancamento.getValor().replace(",", ".")));
			
			if(null != lancamento.getValorCheque24() && !"".equals(lancamento.getValorCheque24().trim())){
				mensagem.setChecks24Amount(new Double(lancamento.getValorCheque24().replace(",", ".")));
			}else{
				mensagem.setChecks24Amount(0d);
			}
			if(null != lancamento.getValorCheque48() && !"".equals(lancamento.getValorCheque48().trim())){
				mensagem.setChecks48Amount(new Double(lancamento.getValorCheque48().replace(",", ".")));
			}else{
				mensagem.setChecks48Amount(0d);
			}
			if(null != lancamento.getNumDocumento() && !"".equals(lancamento.getNumDocumento().trim())){
				mensagem.setDepositFormNumber(new BigInteger(lancamento.getNumDocumento()));
			}
			if(null != lancamento.getCategoria() && !"".equals(lancamento.getCategoria().trim())){
				mensagem.setCategoryId(new BigInteger(lancamento.getCategoria()));
			}
			if(null != lancamento.getComentario()){
				mensagem.setComments(lancamento.getComentario());
			}	
			if(lancamento.getReversalFlag()){
				mensagem.setReversalFlag(true);
				mensagem.setReversalNumber(new BigInteger(lancamento.getReversalNumber()));
			}else{
				mensagem.setReversalFlag(false);
			}
			request.setMsgMovement(mensagem);

			//Criacao do servico e recuperacao da porta
			ProcessAccountApplyExternalMovementsWS_Service service = new ProcessAccountApplyExternalMovementsWS_Service();
			ProcessAccountApplyExternalMovementsWS port = service.getProcessAccountApplyExternalMovementsWSPort();
			
			//criacao do bindingprovider para amarracao do endpoint, mudanca da cadeia de handles
			//e outras mudancas que se queira realizar.
			BindingProvider bindingProvider = (BindingProvider) port;
			enderecoServico = parametrizacao.getEndereco();
			bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, enderecoServico);
			bindingProvider.getBinding().setHandlerChain(handlerChain);
			bindingProvider.getRequestContext().put("javax.xml.ws.client.connectionTimeout", 10000); 
			bindingProvider.getRequestContext().put("javax.xml.ws.client.receiveTimeout", 10000);
			
			
			ProcessAccountApplyExternalMovementsWSResponse response = null;

			
			try{
				
				//chamada do servico
				response = port.processAccountApplyExternalMovementsWS(request, holder);
				
			}catch(MovementFault e){
				
				Errors erros = e.getFaultInfo();
				
				
				if(null != erros){
					
						List<net.technisys.cmm.services.errors.v1.Errors.Error> erroslist = erros.getError();
						
						String errorList = "";
						lancamento.setErrorList(errorList);
						
						if(null != erroslist && !erroslist.isEmpty()){
							for(net.technisys.cmm.services.errors.v1.Errors.Error erro:erroslist){
								errorList += erro.getDetail() +"###";
							}
						}

						lancamento.setErrorList(errorList);
					
				}
				
			}catch(SOAPFaultException se){
				
				lancamento.setErrorList(se.getMessage());
				se.printStackTrace();
				
			}catch(RuntimeException r){
				
				lancamento.setErrorList("Não foi possível conectar o serviço em: "+enderecoServico+"### Causa: "+r.getMessage());
				
			}catch(Exception e){
				
				lancamento.setErrorList(e.getMessage());
				String erro = "";
				
				for(StackTraceElement st:e.getStackTrace()){
					erro += st.toString()+"###";
				}
				
				JDialog d = new JDialog();
				 d.setSize(600, 600);
				 JLabel critica = new JLabel(erro);
				 critica.setForeground(Color.RED);
				 d.add(critica);
				 d.setVisible(true);
				e.printStackTrace();
				
			}
			
			if(null != response){
				
				Msg msg = response.getGeneric().getMsg();
				if(null != msg){
					lancamento.setResposta(msg.getValue());
				}
				
			}
			
			
															  
			
		} catch (Exception e) {
			e.printStackTrace();
			throw new CyberBankException(CBUtil.getMensagem("error.cyberbank.lancamento"), e);
		}
	}
	


}
