package com.rjconsultores.ventaboletos.web.gui.controladores.expressos;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.bind.DatatypeConverter;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.zkoss.util.media.Media;
import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.UploadEvent;
import org.zkoss.zul.Combobox;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Paging;

import com.rjconsultores.ventaboletos.entidad.Articulo;
import com.rjconsultores.ventaboletos.entidad.Ciudad;
import com.rjconsultores.ventaboletos.entidad.Constante;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.SolicitudExpreso;
import com.rjconsultores.ventaboletos.entidad.TrayectosExpresos;
import com.rjconsultores.ventaboletos.service.CiudadService;
import com.rjconsultores.ventaboletos.service.ConstanteService;
import com.rjconsultores.ventaboletos.service.LogAuditoriaService;
import com.rjconsultores.ventaboletos.service.SolicitudExpresosService;
import com.rjconsultores.ventaboletos.service.TrayectosExpresosService;
import com.rjconsultores.ventaboletos.web.utilerias.MyGenericForwardComposer;
import com.rjconsultores.ventaboletos.web.utilerias.MyListbox;
import com.rjconsultores.ventaboletos.web.utilerias.MyTextbox;
import com.rjconsultores.ventaboletos.web.utilerias.paginacion.HibernateSearchObject;
import com.rjconsultores.ventaboletos.web.utilerias.paginacion.PagedListWrapper;
import com.rjconsultores.ventaboletos.web.utilerias.render.RenderTrayectosExpreso;
import com.rjconsultores.ventaboletos.web.utilerias.spring.AppContext;

@Controller("cotizarExpresoController")
@Scope("prototype")
public class CotizarExpresoController extends MyGenericForwardComposer{
	
	private static final long serialVersionUID = 1L;
	
	@Autowired
	private CiudadService ciudadService;
	
	@Autowired
    private transient PagedListWrapper<TrayectosExpresos> plwTrayectosExpresos;
	
	@Autowired
	TrayectosExpresosService trayectosExpresosService;
	
	@Autowired
	SolicitudExpresosService solicitudExpresosService;
	
	@Autowired
	ConstanteService constanteService;
	
	@Autowired
    private LogAuditoriaService logAuditoriaService;
	
	SolicitudExpreso expreso;
	SolicitudExpreso expresoClone;
	
	TrayectosExpresos trayecto;
	TrayectosExpresos trayectoClone;
	
	private MyTextbox txtNumSolicitud;
	private MyTextbox txtRuta;
	private MyTextbox txtIdaRegreso;
	private MyTextbox txtCantPasajeros;
	private MyTextbox txtFechaIda;
	private MyTextbox txtFechaRegreso;
	private MyTextbox txtSitioRecogidaIda;
	private MyTextbox txtSitioRecogidaRegreso;
	private MyTextbox archivoCotizacionPath;
	
	private List<Ciudad> lsOrigen;
	private List<Ciudad> lsDestino;
	private Combobox cmbOrigen;
	private Combobox cmbDestino;
	
	private List<TrayectosExpresos> lsTrayectos = new ArrayList<TrayectosExpresos>();
	private MyListbox trayectosList;
	private Paging pagingTrayectos;
	
	private byte[] docCotizacion;
	
	@Override
	public void doAfterCompose(Component comp) throws Exception {
		
		lsOrigen = ciudadService.obtenerTodos();
		lsDestino = ciudadService.obtenerTodos();
		
		super.doAfterCompose(comp);
		
		expreso = (SolicitudExpreso) Executions.getCurrent().getArg().get("expreso");
		expreso.clonar();
    	expresoClone = expreso.getCloneObject();
		
		trayectosList.setItemRenderer(new RenderTrayectosExpreso());
		trayectosList.addEventListener("onDoubleClick", new EventListener() {

            @Override
            public void onEvent(Event event) throws Exception {
            	trayecto = (TrayectosExpresos) trayectosList.getSelected();
            	
            	Map args = new HashMap();
                
                args.put("trayecto", trayecto);

                openWindow("/gui/expressos/modificarTrayectoCotizar.zul", Labels.getLabel("expresosPorCotizarCotizar.window.title"), args, MODAL);
            }
        });
		
		txtNumSolicitud.setValue(expreso.getSolicitudExpresoId().toString());
		txtRuta.setValue(expreso.getCiudadOrigen().getNombciudad() + " - " + expreso.getCiudadDestino().getNombciudad());
		txtIdaRegreso.setValue(expreso.getIndViajeRedondo() == true ? Labels.getLabel("expresosController.lbl.idaVuelta") : Labels.getLabel("expresosController.lbl.ida"));
		txtCantPasajeros.setValue(expreso.getCantidadPasajeros().toString());
		txtFechaIda.setValue(expreso.getFechaHoraIda().toString());
		txtFechaRegreso.setValue(expreso.getFechaHoraRegreso().toString());
		txtSitioRecogidaIda.setValue(expreso.getDescSitioPartidaIda());
		txtSitioRecogidaRegreso.setValue(expreso.getDescSitioPartidaRegreso());
		
		refreshLista();
	}
	
	private void refreshLista() {
		HibernateSearchObject<TrayectosExpresos> buscarTrayectos =
                new HibernateSearchObject<TrayectosExpresos>(TrayectosExpresos.class, pagingTrayectos.getPageSize());
		
		buscarTrayectos.addFilterEqual("solicitudExpresoId.solicitudExpresoId", expreso.getSolicitudExpresoId());
		
		buscarTrayectos.addFilterEqual("activo", true);
		
		plwTrayectosExpresos.init(buscarTrayectos, trayectosList, pagingTrayectos);
	}
	
	public void onUpload(UploadEvent event) throws IOException, InterruptedException {
		org.zkoss.util.media.Media media = event.getMedia();
		
		if(media.getFormat().toString().equalsIgnoreCase("pdf")) {
			InputStream inputStream = media.getStreamData();
		    byte[] bytesIs = IOUtils.toByteArray(inputStream);
		    
		    docCotizacion = bytesIs;
			
			archivoCotizacionPath.setValue(media.getName());
		}else {
			Messagebox.show(
					Labels.getLabel("expresoController.MSG.errorArchivo") + " " + media,
					Labels.getLabel("expresosPorCotizarCotizar.window.title"),
					Messagebox.OK, Messagebox.ERROR);
		}
	}
	
	public void onClick$btnAgregarTrayecto(Event event) throws Exception {		
		agregarTrayectoExpreso();
	}
	
	public void onClick$btnRefresh(Event event) throws Exception {		
		refreshLista();
	}
	
	public void onClick$btnGuardarCotizacion(Event event)  throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException, Exception {
		if(docCotizacion == null) {
			Messagebox.show(
					Labels.getLabel("expresoController.MSG.errorArchivo"),
					Labels.getLabel("expresosPorCotizarCotizar.window.title"),
					Messagebox.OK, Messagebox.ERROR);
		}else {
			expreso.setDocCotizacion(docCotizacion);
			expreso.setStatusSolicitudExpresoId(2);
			solicitudExpresosService.actualizacion(expreso);
			
			logAuditoriaService.auditar(expresoClone, expreso, null);
			
			enviarEmail();
		}
	}
	
	public void onFocus$winCotizarExpresso(Event event) throws Exception {
		refreshLista();
	}
	
	private void agregarTrayectoExpreso() throws CloneNotSupportedException {
		
		trayecto = new TrayectosExpresos();
		
		trayecto.clonar();
		trayectoClone = trayecto.getCloneObject();
		
		trayecto.setSolicitudExpresoId(expreso);
		trayecto.setDescTrayecto(cmbOrigen.getValue() + " - " + cmbDestino.getValue());
		trayecto.setCantVehiculos(0);
		trayecto.setValorTrayecto(0);
		
		trayectosExpresosService.suscribir(trayecto);
		
		logAuditoriaService.auditar(trayectoClone, trayecto, null);
		
		refreshLista();
	}
	
	private void enviarEmail() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException, ClientProtocolException, IOException, InterruptedException {
		
		String urlAPIRJ = valorConstante("URL_API_RJ_INFOBIP");
		String credenciais = valorConstante("CREDENCIAIS_API_RJ");
		String tenant = valorConstante("TENANT_API_RJ");
		String empresaId = valorConstante("EMPRESA_NOTIFICACOES_BOLIVARIANO");
		
		urlAPIRJ = urlAPIRJ.concat("EnviarEmailGenerico");
		
		CloseableHttpClient httpClient = HttpClients.createDefault();
		
		HttpPost request = new HttpPost(urlAPIRJ);
		
		List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
		urlParameters.add(new BasicNameValuePair("emailCliente", expreso.getDescEmail()));
		urlParameters.add(new BasicNameValuePair("assunto", Labels.getLabel("expresoController.MSG.asuntoCorreoCotizacion")));
		urlParameters.add(new BasicNameValuePair("texto", Labels.getLabel("expresoController.MSG.cuerpoCorreoCotizacion", new Object[] { expreso.getDescNombre() + " " + expreso.getDescApellidos(), "[INSERT LINK HERE]" })));
		urlParameters.add(new BasicNameValuePair("empresaId", empresaId));
		
		UrlEncodedFormEntity params = new UrlEncodedFormEntity(urlParameters, "UTF-8");
		
		request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(credenciais.getBytes())));
		
		if (StringUtils.isNotBlank(tenant)){
			request.addHeader("x-tenant-id", tenant);	
		}
		
		request.setEntity(params);

		CloseableHttpResponse response = httpClient.execute(request);
		
		if(response.getStatusLine().getStatusCode() == 200 && response.getStatusLine().getReasonPhrase().equalsIgnoreCase("OK")) {
			Messagebox.show(
					Labels.getLabel("cotizarExpresoController.MSG.emailEnviado"),
					Labels.getLabel("expresosPorCotizarCotizar.window.title"),
					Messagebox.OK, Messagebox.INFORMATION);
		} else {
			Messagebox.show(
					Labels.getLabel("cotizarExpresoController.MSG.emailNoEnviado"),
					Labels.getLabel("expresosPorCotizarCotizar.window.title"),
					Messagebox.OK, Messagebox.ERROR);
		}
		
		this.closeWindow();
	}
	
	public String valorConstante(String nombreConstante) {
		Constante constante = constanteService.buscarPorNomeConstante(nombreConstante);

		return constante != null ? constante.getValorconstante() : null ;
	}

	public SolicitudExpreso getExpreso() {
		return expreso;
	}

	public void setExpreso(SolicitudExpreso expreso) {
		this.expreso = expreso;
	}

	public Combobox getCmbOrigen() {
		return cmbOrigen;
	}

	public void setCmbOrigen(Combobox cmbOrigen) {
		this.cmbOrigen = cmbOrigen;
	}

	public List<Ciudad> getLsOrigen() {
		return lsOrigen;
	}

	public void setLsOrigen(List<Ciudad> lsOrigen) {
		this.lsOrigen = lsOrigen;
	}

	public List<Ciudad> getLsDestino() {
		return lsDestino;
	}

	public void setLsDestino(List<Ciudad> lsDestino) {
		this.lsDestino = lsDestino;
	}

	public Combobox getCmbDestino() {
		return cmbDestino;
	}

	public void setCmbDestino(Combobox cmbDestino) {
		this.cmbDestino = cmbDestino;
	}

	public Paging getPagingTrayectos() {
		return pagingTrayectos;
	}

	public void setPagingTrayectos(Paging pagingTrayectos) {
		this.pagingTrayectos = pagingTrayectos;
	}
}
