package gov.va.med.esr.ui.util;

import gov.va.med.fw.ui.DelegatingActionUtils;
import gov.va.med.fw.util.StringUtils;

import java.io.PrintWriter;
import java.io.StringWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ExceptionHandler;
import org.apache.struts.config.ExceptionConfig;
import org.springframework.web.context.WebApplicationContext;

public class GenericExceptionHandler extends ExceptionHandler
{
    public static final String DEPLOYMENT_TYPE_LOCAL = "local";
    public static final String INCLUDE_STACK_TRACE_MESSAGE_KEY = "ui.error.include.stacktrace";
    public static final String EXCEPTION_STACK_TRACE_KEY = "exceptionStackTrace";

    //An instance of a logger for logging information
    protected Log logger = LogFactory.getLog(getClass());

    /**
     * Handles(logs) exceptions and returns ActionForward to an application error page configured in the exception
     * config's path attribute. If the deployment type is development(local) generates the stack trace and add it as a
     * request attribute to be used by the application error jsp.
     *
     * @param exception The exception to handle
     * @param exceptionConfig The ExceptionConfig corresponding to the exception
     * @param mapping The ActionMapping we are processing
     * @param formInstance The ActionForm we are processing
     * @param request The servlet request we are processing
     * @param response The servlet response we are creating
     *
     * @throws ServletException if a servlet exception occurs
     */
    public ActionForward execute(Exception exception,
        ExceptionConfig exceptionConfig,
        ActionMapping mapping,
        ActionForm formInstance,
        HttpServletRequest request,
        HttpServletResponse response)
        throws ServletException
    {
        // Default application error url.
        String applicationErrorPath = "error";
        try
        {
            applicationErrorPath = exceptionConfig.getPath();
            if (StringUtils.isEmpty(applicationErrorPath))
            {
                applicationErrorPath = "error";
            }
            logger.error("Going to display application error page with URL = " + applicationErrorPath, exception);
            
            // Get the "include stack trace" property from the deployment environment property file.
            // If not configured, assume false
            HttpSession session = request.getSession();
				WebApplicationContext ac = DelegatingActionUtils.findRequiredWebApplicationContext( session.getServletContext() );
            boolean stackTraceVisible =
                ((Boolean) ac.getBean(INCLUDE_STACK_TRACE_MESSAGE_KEY)).booleanValue();
            
            // If we have an exception and the flag is on, print the stack trace on the screen
            if (exception != null && stackTraceVisible)
            {
                StringWriter stringWriter = new StringWriter();
                PrintWriter printWriter = new PrintWriter(stringWriter);
                exception.printStackTrace(printWriter);
                printWriter.flush();
                String trace = stringWriter.toString();
                if (StringUtils.isNotEmpty(trace))
                {
                    request.setAttribute(EXCEPTION_STACK_TRACE_KEY, trace);
                }
            }
        }
        catch (Exception ex)
        {
            logger.error("Error while handling the exception", ex);
        }
        return new ActionForward(mapping.findForward(applicationErrorPath));
    }
}