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

import java.awt.Color;
import java.io.File;
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.processuserloginbackoffice.rq.v1.Branch;
import net.technisys.cmm.services.processuserloginbackoffice.rq.v1.Channel;
import net.technisys.cmm.services.processuserloginbackoffice.rq.v1.Institution;
import net.technisys.cmm.services.processuserloginbackoffice.rq.v1.ProcessUserLoginBackofficeRequest;
import net.technisys.cmm.services.processuserloginbackoffice.rq.v1.SystemUser;
import net.technisys.cmm.services.seguridad.v1.LoginFault;
import net.technisys.cmm.services.seguridad.v1.ProcessUserLoginBackoffice;
import net.technisys.cmm.services.seguridad.v1.Seguridad;
import br.com.bancooriginal.cyberbank.dto.Parametrizacao;
import br.com.bancooriginal.cyberbank.exception.CyberBankException;
import br.com.bancooriginal.cyberbank.util.SessionIdGenerator;
import br.com.bancooriginal.cyberbank.util.XMLUtil;

/**
 * Classe cliente do servico que cria a sessao no cyberbank processUserLoginBackoffice.
 * Esta classe monta o request, chama o servico e trata o retorno.
 * 
 * @author filipe.sa
 *
 */
public class SecurityClient {
	
	String enderecoServico;
	
	String resposta;

	
	@SuppressWarnings("rawtypes")
	public void autenticar() throws CyberBankException{
		
		try {
			
			String novasessao = SessionIdGenerator.generateSessionId();
			
			//Leitura da parametrizacao do servico
			Parametrizacao parametrizacao = XMLUtil.lerConfiguracoes(new File("parametrizacao.xml"));
			
	    	//Criacao do objeto metadata que sera o header da mensagem
			Metadata metadata = new Metadata();
			
			//Parametros fixos
			metadata.setServiceId("processUserLoginBackoffice");
			metadata.setServiceVersion("1.0");
			metadata.setServiceContext("Tech");
			
			SimpleDateFormat sd = new SimpleDateFormat("yyyyMMddHHMMsshhh");

			//parametros provenientes da parametrizacao
			metadata.setChannelDispatchDate(sd.format(new Date()));
			metadata.setSessionId(novasessao);
			metadata.setUserId(parametrizacao.getUserId());
			metadata.setExecutingOperatorId(parametrizacao.getUserId());
			metadata.setInstitutionId(parametrizacao.getInstitutionId());
			metadata.setBranchId(parametrizacao.getBranchId());
			//metadata.setTraceNumber("275451.189999");
			//<serviceRequestTimestamp>20140715171634846</serviceRequestTimestamp>
			
			CustomProperties custom = new CustomProperties();
			custom.setServiceContext("Tech");
			metadata.setCustomProperties(custom);
			
			ExecutingChannel executingChannel = new ExecutingChannel();
			executingChannel.setMnemonic("8");
			metadata.setExecutingChannel(executingChannel);
			
			//Criamos o objeto que sera o request da mensagem
			ProcessUserLoginBackofficeRequest request = new ProcessUserLoginBackofficeRequest();
			
			Branch branch = new Branch();
			branch.setBranchId(parametrizacao.getBranchId());
			branch.setId(parametrizacao.getBranchId());
			branch.setName("branch");
			branch.setDataModel("product.financials");
			branch.setVersion("1.0");
			
			Channel channel = new Channel();
			channel.setChannelId("8");
			channel.setName("channel");
			channel.setDataModel("product.financials");
			channel.setVersion("1.0");
			
			Institution institution = new Institution();
			institution.setInstitutionId(parametrizacao.getInstitutionId());
			institution.setName("institution");
			institution.setDataModel("product.financials");
			institution.setVersion("1.0");
			
			SystemUser systemUser = new SystemUser();
			systemUser.setUserId(parametrizacao.getUserId());
			systemUser.setName("user");
			systemUser.setDataModel("product.financials");
			systemUser.setVersion("1.0");
			
			request.setBranch(branch);
			request.setChannel(channel);
			request.setInstitution(institution);
			request.setSystemUser(systemUser);

			
			//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 servico e recuperacao da porta
			ProcessUserLoginBackoffice service = new ProcessUserLoginBackoffice();
			Seguridad port = service.getProcessUserLoginBackofficePort();
			
			//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);			
			
			//ProcessUserLoginBackofficeResponse response = null;

			
			try{
				
				//chamada do servico
				//response = port.processUserLoginBackoffice(request, holder);
				port.processUserLoginBackoffice(request, holder);
				
			}catch(LoginFault e){
				
				e.printStackTrace();
				
				Errors erros = e.getFaultInfo();
				
				
				if(null != erros){
					
						List<net.technisys.cmm.services.errors.v1.Errors.Error> erroslist = erros.getError();
						
						resposta = "";
						
						if(null != erroslist && !erroslist.isEmpty()){
							for(net.technisys.cmm.services.errors.v1.Errors.Error erro:erroslist){
								resposta += erro.getDetail() +"###";
							}
						}
						
						throw new CyberBankException(resposta);
					
				}
				
			}catch(SOAPFaultException se){
				
				se.printStackTrace();
				
				throw new CyberBankException(se.getMessage());
				
			}catch(RuntimeException r){
				
				r.printStackTrace();
				
				throw new CyberBankException("Não foi possível conectar o serviço em: "+enderecoServico+"### Causa: "+r.getMessage());
				
			}catch(Exception e){
				
				e.printStackTrace();
				
				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();
				
				throw new CyberBankException(e.getMessage());
				
			}
			
			XMLUtil.escreverAtributoParametrizacao("sessionId", novasessao);
															  
			
		} catch (Exception e) {
			
			e.printStackTrace();
			throw new CyberBankException(e.getMessage());
			
		}
	}
	
	

}
