package managedbean.common;

import java.io.IOException;
import java.io.Serializable;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;

import common.Utils;

/***
 * 
 * @author Marcos García Núñez (mgarcianun@uoc.edu)
 *
 */
@Named("error")
@RequestScoped
public class errorMBean extends ManagedBeanBase implements Serializable {

	private static final long serialVersionUID = 1L;
	private String errorType;
	private String errorMessage;
	private String requestURI;
	private boolean renderBack;

	@PostConstruct
	public void init() throws IOException {
		FacesContext fc = FacesContext.getCurrentInstance();
		this.setRenderBack(false);

		if (fc != null) {
			HttpServletRequest req = (HttpServletRequest) fc.getExternalContext().getRequest();

			Map<String, String> requestParams = fc.getExternalContext().getRequestParameterMap();

			this.errorType = this.getRequestParameter(requestParams, "type");
			if (this.errorType.equals("") == true) {
				this.requestURI = this.getRequestAttribute(req, "javax.servlet.error.request_uri");

				if (requestURI.equals("") == true)
					this.requestURI = req.getContextPath().concat("/home.xhtml");

				setRenderBack(true);

				Throwable rootCause = null;
				Object obj = req.getAttribute("javax.servlet.error.exception");
				if (obj != null) {
					Exception se = Exception.class.cast(obj);

					rootCause = Utils.getExceptionRootCause(se);

					if (rootCause != null) {
						this.errorType = rootCause.getClass().getName();
						this.errorMessage = rootCause.getLocalizedMessage();
					} else {
						this.errorType = se.getClass().getName();
						this.errorMessage = se.getCause().getLocalizedMessage();
					}
				}

				// Si no hay error volvemos al home.
				if (this.errorType.equals("") == true)
					fc.getExternalContext().redirect(req.getContextPath().concat("/home.xhtml"));

				switch (this.errorType) {
				case "javax.faces.application.ViewExpiredException":
					this.errorType = "expired";
					this.addFacesMessage(FacesMessage.SEVERITY_WARN, "Sesión caducada", "Su sesión ha caducado, debe logearse de nuevo");
					break;
				case "java.sql.SQLException":
				case "org.hibernate.exception.GenericJDBCException":
				case "java.net.ConnectException":
				case "javax.persistence.PersistenceException":
					this.errorType = "sql";
					this.addFacesMessage(FacesMessage.SEVERITY_ERROR, "Error en el acceso a la base de datos", this.errorMessage);

					break;
				default:
					this.errorType = "runtime";
					this.addFacesMessage(FacesMessage.SEVERITY_ERROR, "Error interno del servidor", this.errorMessage);
				}
			}
		}
	}

	private String getRequestAttribute(HttpServletRequest req, String attrName) {
		Object attr = req.getAttribute(attrName);

		if (attr != null)
			return attr.toString();
		else
			return "";
	}

	private String getRequestParameter(Map<String, String> pars, String paramName) {
		Object par = pars.get(paramName);

		if (par != null)
			return par.toString();
		else
			return "";
	}

	public String getErrorType() {
		return errorType;
	}

	public void setErrorType(String errorType) {
		this.errorType = errorType;
	}

	public String getRequestURI() {
		return requestURI;
	}

	public void setRequestURI(String requestURI) {
		this.requestURI = requestURI;
	}

	public boolean isRenderBack() {
		return renderBack;
	}

	public void setRenderBack(boolean renderBack) {
		this.renderBack = renderBack;
	}

	public String getErrorMessage() {
		return errorMessage;
	}

	public void setErrorMessage(String errorMessage) {
		this.errorMessage = errorMessage;
	}

}
