package com.fp.frontend.helper;

import java.security.MessageDigest;
import java.util.Map;

import javax.ejb.EJB;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;

import com.fp.dto.Request;
import com.fp.dto.Response;
import com.fp.facadeclient.ejb.FacadeBeanJsfRemote;
import com.fp.facadeclient.helper.ServiceLocatorJsf;
import com.fp.frontend.controller.security.LoginController;

/**
 * Clase utilitaria que se encarga de ejecutar acciones en el core.
 *
 * @author Jorge Vaca.
 * @version 2.1
 */
public class CallerHelper {

    @EJB
    private FacadeBeanJsfRemote fremote;

    private final Request request;

    public CallerHelper() throws Exception {
        // se utiliza en el login
        this.request = new Request();
    }

    /**
     * Constructor de la clase utilitaria para realizar las peticiones hacia el
     * core
     *
     * @param facesContext
     * @throws Exception
     */
    public CallerHelper(FacesContext facesContext) throws Exception {
        LoginController logincontroler = (LoginController) facesContext.getExternalContext().getSessionMap().get("loginController");
        Map<String, String[]> params = facesContext.getExternalContext().getRequestParameterValuesMap();
        String m = "";
        Integer t = 0;
        Integer v = 0;
        if ((params.get("m") == null) && (params.get("t") == null)) {
            // Object[] tran = (Object[])params.get("tran"); ejemplo de prametros de un dialogo en runtime ejemplo LOV.
            m = logincontroler.getRequest().getTransactionModule();
            t = logincontroler.getRequest().getTransactionCode();
            v = logincontroler.getRequest().getTransactionVersion();
        } else {
            Object[] maux = params.get("m");
            Object[] taux = params.get("t");
            Object[] vaux = params.get("v");
            m = (String) maux[0];
            t = Integer.valueOf((String) taux[0]);
            v = Integer.valueOf((String) vaux[0]);
            logincontroler.getRequest().setTransactionModule(m);
            logincontroler.getRequest().setTransactionCode(t);
            logincontroler.getRequest().setTransactionVersion(v);
        }

        this.request = new Request();
        try {
            logincontroler.fijaRequestData(this.request, m, t, v);
        } catch (NullPointerException e) {
            Response r = new Response("BGEN-0000", "USUARIO NO HA INICIADO SESSION DE TRABAJO");
            MessageHelper.setMessageError(r);
        }
    }

    /**
     * Metodo que ejecuta consultas, en el core de maia.
     *
     * @param request Request que contiene la metadata de consultas.
     * @return Response
     * @throws Throwable
     */
    public Response executeQuery(Request request) throws Throwable {
        // siempre obtener una referencia al ejb de consulta del servicelocator.
        this.fremote = ServiceLocatorJsf.getInstance().getFacadeRemote("querybean");
        Response resp = (Response) this.fremote.process(request);
        
        return resp;
    }

    /**
     * Metodo que ejecuta insert, update, delete, en el core de maia.
     *
     * @param request Request que contiene la metadata del mantenimiento
     * @return Response
     * @throws Throwable
     */
    public Response executeSave(Request request) throws Throwable {
        // siempre obtener una referencia al ejb de consulta del servicelocator.
        this.fremote = ServiceLocatorJsf.getInstance().getFacadeRemote("savebean");
        Response resp = (Response) this.fremote.process(request);
        return resp;
    }
/**
 *Ejecutar query Nativo
 */
    public int executeNativeQuery(String query) throws Exception{
        this.fremote = ServiceLocatorJsf.getInstance().getFacadeRemote("querybean");
        return this.fremote.executeNativeQuery(query);
    }
    
    
    /**
     * Metodo que ejecuta insert, update, delete, en el core de maia.
     *
     * @param request Request que contiene la metadata del mantenimiento
     * @return Response
     * @throws Throwable
     */
    public boolean executeReport(Request request) throws Throwable {
        // siempre obtener una referencia al ejb de consulta del servicelocator.
        this.fremote = ServiceLocatorJsf.getInstance().getFacadeRemote("reportbean");
        Object resp = this.fremote.process(request);
        return (Boolean) resp;
    }

    /**
     * Metodo que ejecuta insert, update, delete, en el core de maia.
     *
     * @param request Request que contiene la metadata del mantenimiento
     * @return Response
     * @throws Throwable
     */
    public Response login(Request request, String user, String password) throws Throwable {
        request.setUser(user);
        request.put("itemValue", this.getPasswordEncriptado(password));
        request.setTransactionModule("1");
        request.setTransactionCode(9998);
        request.setTransactionVersion(1);
        request.put("querytype", "T");
        HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
        request.modifiedData().put("jsessionid", session.getId());
        // siempre obtener una referencia al ejb de consulta del servicelocator.
        this.fremote = ServiceLocatorJsf.getInstance().getFacadeRemote("querywithcommitbean");
        Response resp = (Response) this.fremote.process(request);
        return resp;
    }

    /**
     * Metodo que ejecuta insert, update, delete, en el core de maia.
     *
     * @param request Request que contiene la metadata del mantenimiento
     * @return Response
     * @throws Throwable
     */
    public Response loginCas(Request request, String user, String password) throws Throwable {
        request.put("itemValue", this.getPasswordEncriptado(password));
        request.setTransactionModule("1");
        request.setTransactionCode(9997);
        request.setTransactionVersion(1);
        request.put("querytype", "T");
        // siempre obtener una referencia al ejb de consulta del servicelocator.
        this.fremote = ServiceLocatorJsf.getInstance().getFacadeRemote("querywithcommitbean");
        Response resp = (Response) this.fremote.process(request);
        return resp;
    }

    /**
     * Metodo que ejecuta insert, update, delete, en el core de maia.
     *
     * @param request Request que contiene la metadata del mantenimiento
     * @return Response
     * @throws Throwable
     */
    public Response logout(Request request) throws Throwable {
        request.setTransactionModule("1");
        request.setTransactionCode(9999);
        request.setTransactionVersion(1);
        // siempre obtener una referencia al ejb de consulta del servicelocator.
        this.fremote = ServiceLocatorJsf.getInstance().getFacadeRemote("savebean");
        Response resp = (Response) this.fremote.process(request);
        return resp;
    }

    /**
     * Entrega el password encriptado.
     *
     * @param password Password a encriptar.
     * @return String
     * @throws Exception
     */
    public String getPasswordEncriptado(String password) throws Exception {
        if (password == null) {
            return null;
        }
        MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
        messageDigest.reset();
        messageDigest.update(password.getBytes());
        String encriptado = toHexadecimal(messageDigest.digest());
        return encriptado;
    }

    /**
     * Metodo que ejecuta insert, update, delete, en el core de maia.
     *
     * @param request Request que contiene la metadata del mantenimiento
     * @return Response
     * @throws Throwable
     */
    public Response menu(Request request) throws Throwable {
        Request rq = new Request();
        rq.setCompany(request.getCompany());
        rq.setProfile(request.getProfile());
        rq.setLanguage(request.getLanguage());
        rq.setTransactionModule(null);
        rq.setTransactionCode(null);
        rq.setTransactionVersion(null);
        rq.put("querytype", "P");
        rq.put("queryalias", "MENU");
        // siempre obtener una referencia al ejb de consulta del servicelocator.
        this.fremote = ServiceLocatorJsf.getInstance().getFacadeRemote("querywithcommitbean");
        Response resp = (Response) this.fremote.process(rq);
        return resp;
    }

    private static String toHexadecimal(byte[] digest) {
        String hash = "";
        for (byte aux : digest) {
            int b = aux & 0xff;
            if (Integer.toHexString(b).length() == 1) {
                hash += "0";
            }
            hash += Integer.toHexString(b);
        }
        return hash;
    }

    /**
     * Verifica el parametro de la pagina autoquery es Y.
     *
     * @return boolean
     * @throws Exception
     */
    public boolean isautoquery() throws Exception {
        Map<String, String> m = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
        if ((m.get("autoquery") != null) && "Y".equals(m.get("autoquery"))) {
            return true;
        }
        return false;
    }

    /**
     * Entrega el valor de un parametro del lov. Si no existe retorna null.
     *
     * @param parametername Nombre del parametro.
     * @return String.
     * @throws Exception
     */
    public static String getLovParameter(String parametername) throws Exception {
        Map<String, String[]> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterValuesMap();
        String[] obj = params.get(parametername);
        if (obj == null) {
            return null;
        }
        return obj[0];
    }

    /**
     * Entrega el valor de: request
     *
     * @return Request
     */
    public Request getRequest() {
        return this.request;
    }

    public Request getNewRequest(String module, Integer transaction, Integer version) throws Exception {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        LoginController logincontroler = (LoginController) facesContext.getExternalContext().getSessionMap().get("loginController");

        Request newRequest = new Request();
        try {
            logincontroler.fijaRequestData(newRequest, module, transaction, version);
        } catch (NullPointerException e) {
            Response r = new Response("BGEN-0000", "USUARIO NO HA INICIADO SESSION DE TRABAJO");
            MessageHelper.setMessageError(r);
        }
        return newRequest;
    }

}
