package com.fitbank.web;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.rmi.RemoteException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.myfaces.config.RuntimeConfig;
import org.apache.myfaces.config.impl.digester.elements.NavigationCase;
import org.apache.myfaces.config.impl.digester.elements.NavigationRule;

import com.fitbank.common.ApplicationDates;
import com.fitbank.common.exception.FitbankException;
import com.fitbank.common.logger.FitbankLogger;
import com.fitbank.dto.management.Detail;
import com.fitbank.dto.management.Record;
import com.fitbank.dto.management.Table;
import com.fitbank.exception.ExceptionHandler;
import javax.servlet.ServletRequest;

public class FacesUtil {
	private DataManage dm;
	private ServletRequest request;
	private Map<String,String> sendingParams=new HashMap<String, String>();
  public FacesUtil(){
  	
  }
  public FacesUtil(DataManage pDataManager,ServletRequest pRequest){
  	this.request=pRequest;
  	dm = pDataManager;
		prepareParameters();
		try {
			bindData();
		} catch (Exception e) {
			e.printStackTrace();
		}
  }
  public FacesUtil(DataManage pDataManager) {
  	this(pDataManager,true);
  }
	public FacesUtil(DataManage pDataManager,boolean pBind) {
		dm = pDataManager;
		prepareParameters();
		try {
			if(pBind)
			bindData();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@SuppressWarnings("unchecked")
	public String getRequestParametersData() throws Exception {
		Set<String> paramName = getParameterNames();
		String data = "";
		for (String name : paramName) {

			data += "[" + name + "]" + getParameterString(name);
		}
		return data;
	}

	protected void addErrorMessage(Throwable pError) {
		if (pError instanceof FitbankException) {
			FitbankException res = ((FitbankException) pError);
			// this.addMessage(res.getCode() + ":" + res.getMessage());
			this.addMessage(res.getMessage());
			return;
		}
		if (pError instanceof RemoteException) {
			pError = pError.getCause();
		}
		FitbankLogger.getLogger().error("ERROR>>>>>", pError);
		ExceptionHandler eh = new ExceptionHandler(pError, "es");
		this.addMessage(eh.getUserMessage());
		// this.addMessage(eh.getTechnicalMessage());
	}

	protected void addMessage(String pData) {
		try{
		 if(this.dm!=null){
                     if(pData.compareTo("TRANSACCION REALIZADA CORRECTAMENTE")!=0){
                       this.dm.getMessages().add(pData);
                     }
                 }
                    //FacesMessage fm = new FacesMessage(pData);
		//FacesContext.getCurrentInstance().addMessage("", fm);
		}catch(Exception e){
			
		}
	}

        private void prepareParameters() {
	  this.prepareParameters(this.request);
	}
        
	@SuppressWarnings("unchecked")
	private void prepareParameters(ServletRequest req) {
		Enumeration<String> en = this.getRequest().getParameterNames();
		ParamMap param = new ParamMap(this.dm,this.getRequest());
		while (en.hasMoreElements()) {
			String key = (String) en.nextElement();
			if(!validateParamKey(key)){
				continue;
			} 
			if(key.indexOf("p_")==0){
				String val= getParameterString(key);
				this.sendingParams.put(key.substring(2), val);
			}
			if(key.indexOf("e_")==0){
				String val= getParameterString(key);
				this.sendingParams.put(key, val);
			}
			if (key.indexOf("dm.") == 0) {
				continue;
			}
			param.put(key, getParameterString(key));
		}
		this.dm.put("param", param);
    
	}

	private void bindData() throws Exception {
		new BindHelper(this);
	}

	private boolean validateParamKey(String pKey)  {
		if (pKey.indexOf(":") > -1) {
			return false;
		}
		List<String> list =new ArrayList<String>();
		 try{
			 list =HBParam.getInstance().getList("json.capture.exclude");
		 }catch(Exception e){
			 list =new ArrayList<String>();
		 }
		for (String key : list) {
			if (key.trim().compareTo(pKey) == 0) {
				return false;
			}
		}
		return true;
	}

	public String captureData() throws Exception {
		String data = "";
		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		PrintStream ps = new PrintStream(bout);
		ps.println("{ identifier:'name', items: [");
		Set<String> keys = this.getParameterNames();
		boolean first = true;

		for (String key : keys) {
			if (!validateParamKey(key)) {
				continue;
			}
			if (first) {
				first = false;
			} else {
				ps.println(",");
			}
			String val = getParameterString(key);
			val = val.replaceAll("'", "\\'");
			ps.print("{");
			ps.print("name:'" + key + "',");
			ps.print("value:'" + val + "'");
			ps.print("}");
		}
		ps.println("]}");
		data = new String(bout.toByteArray());
		return data;
	}

	public void capture(Detail det) throws Exception {
		String capture = getParameterString(DataManage.PARAM_CAPTURE);
		if (capture != null && capture.compareTo("1") == 0) {
			String data = this.captureData();
			String captureName = getParameterString(DataManage.PARAM_CAPTURE_NAME);

			Table tbl = det.findTableByAlias("mf");
			if (tbl == null) {
				tbl = new Table("TMOVIMIENTOSFRECUENTES", "mf");
			} else {
				tbl.clearRecords();
			}
			if (captureName == null || captureName.compareTo("") == 0) {
				return;
			}
			Record rec = new Record();
			tbl.addRecord(rec);
			rec.findFieldByNameCreate("CUSUARIO").setRealValue(det.getUser());
			rec.findFieldByNameCreate("NOMBRETRANSACCION").setRealValue(captureName);
			rec.findFieldByNameCreate("CSUBSISTEMA").setRealValue(det.getSubsystem());
			rec.findFieldByNameCreate("CTRANSACCION").setRealValue(det.getTransaction());
			rec.findFieldByNameCreate("VERSIONTRANSACCION").setRealValue(det.getVersion());
			rec.findFieldByNameCreate("FHASTA").setRealValue(ApplicationDates.getDefaultExpiryDate());
			rec.findFieldByNameCreate("FDESDE").setRealValue(new Timestamp(System.currentTimeMillis()));
			rec.findFieldByNameCreate("DATOS").setRealValue(data);
			det.addTable(tbl);
		}
	}

	public void setRequest(ServletRequest request) {
		this.request = request;
	}
	@SuppressWarnings("unchecked")
	public void createNavigationRule(String pName, String pNamepage) throws Exception {
		ExternalContext externalContext = getExternalContext();
		RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(externalContext);
		Iterator itrule = runtimeConfig.getNavigationRules().iterator();
		NavigationRule nr = null;
		while (itrule.hasNext()) {
			NavigationRule nrule = (NavigationRule) itrule.next();
			Iterator itrcase = nrule.getNavigationCases().iterator();

			while (itrcase.hasNext()) {
				NavigationCase ncase = (NavigationCase) itrcase.next();
				if (ncase.getFromOutcome().compareTo(pName) == 0) {
					return;
				}
				FitbankLogger.getLogger().debug("<><><><><><><>" + ncase.getFromAction() + "   " + ncase.getFromOutcome() + " " + ncase.getToViewId());
				if (ncase.getFromAction() == null && nr == null) {
					nr = nrule;
				}
			}
		}

		NavigationCase nc = new NavigationCase();

		nc.setRedirect();
		nc.setFromOutcome(pName);
		nc.setToViewId(pNamepage);
		if (pNamepage.charAt(0) != '/') {
			nc.setToViewId("/" + pNamepage);
		}

		nr.addNavigationCase(nc);
		FitbankLogger.getLogger().debug("************" + nc.getFromAction() + "   " + nc.getFromOutcome() + " " + nc.getToViewId());
		// runtimeConfig.addNavigationRule(nr);
		runtimeConfig.setNavigationRulesChanged(true);

	}

	public HttpSession getSession() {
		//if(this.request!=null){
			return this.dm.getHttpSession();
		//}
		//return (HttpSession) this.getExternalContext().getSession(true);
	}

	public ServletRequest getRequest() {
		if(this.request!=null){
			return this.request;
		}
		return (HttpServletRequest) this.getExternalContext().getRequest();
	}

	public String getSessionString(String pKey) {
		return (String) this.getSession().getAttribute(pKey);
	}

	public Integer getSessionInteger(String pKey) {
		return (Integer) this.getSession().getAttribute(pKey);
	}

	public String getParameterString(String pKey) {
		return this.getParameterString(pKey, true);
	}
 @SuppressWarnings("unchecked")
private Map getRequestParameterMap(){
	 if(this.request!=null)
	  return request.getParameterMap();
	 return this.getExternalContext().getRequestParameterMap();
 }
	public String getParameterString(String pKey, boolean pRecheck) {
		try{
		String val =(String)this.getRequestParameterMap().get(pKey);
		if (val == null && pRecheck) {
			ParamMap param = (ParamMap) dm.get("param");
			if (param != null) {
				val = (String) param.get(pKey);
			}
		}
		return val;
		}catch(ClassCastException e){
			FitbankLogger.getLogger().debug("Parametro con Error "+pKey);			
			return ((String[])this.getRequestParameterMap().get(pKey))[0];
		}
	}

	@SuppressWarnings("unchecked")
	public Set<String> getParameterNames() {
		return (Set<String>) getRequestParameterMap().keySet();
	}

	public ExternalContext getExternalContext() {
		return FacesContext.getCurrentInstance().getExternalContext();
            //return this.dm.request.getSession().getServletContext();
	}

	public Transaction getTransactionMetaData() {
		String key = DataManage.TRN_DATA;
		String paramKey = this.getParameterString("_detail_");
		if (paramKey != null && paramKey.compareTo("") != 0) {
			key = paramKey;
		} else {
			paramKey = this.getSessionString("_detail_");

			if (paramKey != null && paramKey.compareTo("") != 0) {
				key = paramKey;
			}
		}

		return (Transaction) this.getSession().getAttribute(key);
	}

	public DataManage getDm() {
		return dm;
	}

	public void setDm(DataManage dm) {
		this.dm = dm;
	}
	public Map<String, String> getSendingParams() {
		return sendingParams;
	}

}
