package tvark.jsf;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.ResourceBundle;

import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class JsfUtils {

	public static class Outcome {
		
		public static String PARAMETERS = "parameters";
		
		public static String METHOD = "method";
		
		public static String PARAMETERS_MC = "parametersMc";
		
		public static String PARAMETERS_SA = "parametersSa";
		
		public static String PARAMETERS_BAYES = "parametersBayes";
		
		public static String RESULTS = "results";		
	}
	
	public static class ViewId {
		
		public static String RESULTS = "/results.jsp";
		
		public static String RESULT_PARAMS = "/result-parameters.jsp";
		
		public static String UPLOAD = "/upload.jsp";
		
		public static String PARAMETERS = "/parameters.jsp";
		
		public static String PARAMETERS_MC = "/parameters-mc.jsp";
		
		public static String PARAMETERS_BAYES = "/parameters-bayes.jsp";
		
		public static String PARAMETERS_SA = "/parameters-sa.jsp";
		
		public static String METHOD = "/method.jsp";
	
	}
	
	public static String format(String pKey, Object... pParams) {
		FacesContext ctx = FacesContext.getCurrentInstance();
		ResourceBundle bundle = ResourceBundle.getBundle(
				ctx.getApplication().getMessageBundle(),
				ctx.getViewRoot().getLocale());
		String format = bundle.getString(pKey);
		return MessageFormat.format(format, pParams);
	}
	
	public static void restart() {
		FacesContext ctx = FacesContext.getCurrentInstance();
		HttpServletRequest req = (HttpServletRequest) ctx.getExternalContext().getRequest();
		HttpServletResponse resp = (HttpServletResponse) ctx.getExternalContext().getResponse();
		
		try {
			resp.sendRedirect(req.getContextPath() + "/jsf/index.jsp");
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		ctx.responseComplete();
	}
	
	public static <T> T getValue(String pExpression, Class<T> pType) {
		FacesContext ctx = FacesContext.getCurrentInstance();
		ExpressionFactory f = ctx.getApplication().getExpressionFactory();
		ELContext elctx = ctx.getELContext();
		return pType.cast(f.createValueExpression(elctx, pExpression, pType).getValue(elctx));
	}
	
	public static Object getRequestAttribute(String pAttribute) {
		HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
		return req.getAttribute(pAttribute);
	}
	
	public static boolean containsRequestAttribute(String pAttribute) {
		HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
		Enumeration<?> names = req.getAttributeNames();
		while (names.hasMoreElements()) {
			if (names.nextElement().toString().equals(pAttribute)) {
				return true;
			}
		}
		return false;
	}
	
	public static void setRequestAttribute(Object pValue, String pAttribute) {
		HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
		req.setAttribute(pAttribute, pValue);
	}
	
	public static void serialize(Object pObject, OutputStream pOutputStream) {
		try {
			ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(pOutputStream));
			oos.writeObject(pObject);
			oos.flush();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	public static Object deserialize(InputStream pInputStream) {
		try {
			ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(pInputStream));
			return ois.readObject();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}		
	}
	
	private static File getSessionDir() {
		HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
		String dir = System.getProperty("java.io.tmpdir") + "/" + session.getId();
		File dirf = new File(dir);
		dirf.mkdir();
		return dirf;
	}
	
	public static void persistInSession(Object pObject, String pKey) {
		try {
			FileOutputStream fos = new FileOutputStream(getSessionDir().getAbsolutePath() + "/" + pKey);
			serialize(pObject, fos);
			fos.close();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}		
	}
	
	public static Object loadFromSession(String pKey) {
		try {
			File f = new File(getSessionDir().getAbsolutePath() + "/" + pKey);
			if (!f.exists()) {
				return null;
			}
			FileInputStream fis = new FileInputStream(getSessionDir().getAbsolutePath() + "/" + pKey);
			Object result = deserialize(fis);
			fis.close();
			return result;		
		} catch (IOException e) {
			throw new RuntimeException(e);			
		}
	}
}
