package it.mice.voila.runtime.springmvc.interceptors;

import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import it.mice.voila.runtime.entity.OperationLogMessage;
import it.mice.voila.runtime.security.OperationConfigAttribute;
import it.mice.voila.runtime.security.SecurityUtils;
import it.mice.voila.runtime.springmvc.controller.DefaultController;
import it.mice.voila.runtime.springmvc.flashmap.FlashMap;
import it.mice.voila.runtime.springmvc.form.JfFormBean;
import it.mice.voila.runtime.springmvc.util.SpringMvcUtil;
import it.mice.voila.runtime.util.VelocityContextUtils;

/**
 * Spring mvc interceptor that mantain the path stack chain for go back facility.
 */
public class OperationAuditInterceptor extends HandlerInterceptorAdapter {
	public static final String OPERATION_CONFIG_ATTRIBUTE = "OPERATION_CONFIG_ATTRIBUTE";
	/**
	 * default logger.
	 */
	Log log = LogFactory.getLog(OperationAuditInterceptor.class);
	
	@Autowired
    private VelocityEngine velocityEngine;

	/* (non-Javadoc)
	 * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter#afterCompletion(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)
	 */
	@Override
	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex)
			throws Exception {

		OperationConfigAttribute operationConfigAttribute = (OperationConfigAttribute)SpringMvcUtil.getRequestParameterOrAttribute(OPERATION_CONFIG_ATTRIBUTE);
		if (operationConfigAttribute == null) {
			return;
		}
//		request.removeAttribute(OPERATION_CONFIG_ATTRIBUTE);
		Object handlerBean = SpringMvcUtil.getHandlerBean(handler);
		if (FlashMap.getMessages().hasErrors()) {
			return;
		}
		if (handlerBean instanceof DefaultController) {
			JfFormBean form = SpringMvcUtil.getForm((HandlerMethod)handler);
			if (form != null && operationConfigAttribute.isAuditEnabled() && operationConfigAttribute.getAuditData() != null) {
		        try {
		        	Map<String, Object> ctx = new HashMap<String, Object>();
		            VelocityContext context = new VelocityContext(VelocityContextUtils.getVelocityContextToolsMap());
	                ctx.put("form", form);
//		            ctx.put("user", authentication.getPrincipal());
//		            ctx.put("roles", authentication.getAuthorities());
//		            ctx.put("currentRole", currentRole);

		        	context.put("ctx", ctx);

		        	String logString = "AuditLog";
		            StringWriter sw = new StringWriter();
		            if (velocityEngine.evaluate(context, sw, logString, operationConfigAttribute.getAuditData())) {
		                if (log.isDebugEnabled())
		                    log.debug("Template value:\n" + operationConfigAttribute.getAuditData() + "\nWas converted to:" + sw.toString());
		                
						Log auditLog = LogFactory.getLog("voila.auditing." + operationConfigAttribute.getOperationName());
		                
						OperationLogMessage operationLogMessage = new OperationLogMessage();
						operationLogMessage.setApplicationId(operationConfigAttribute.getApplicationId());
						operationLogMessage.setOperationId(operationConfigAttribute.getOperationId());
						operationLogMessage.setOperationName(operationConfigAttribute.getOperationName());
						operationLogMessage.setIpAddress(SpringMvcUtil.getRequest().getRemoteHost());
						operationLogMessage.setLogDescription(sw.toString());
						operationLogMessage.setCreateUser(SecurityUtils.getCurrentUserId());
						
		                auditLog.info(operationLogMessage);
		            } else {
		                log.error("Failed to parse Velocity content for Auditing Data field template:" + operationConfigAttribute.getAuditData()
		                        + ". Check content into column 'Audit Data' of the table 'Adf Elementary Operation' for operation id " + operationConfigAttribute.getOperationId() + ". Probably the content is not a valid Velocity script language.");
		                log.error("Error description:" + logString);
		            }
		        } catch (Exception e) {
		            log.error("Failed to parse Velocity content for Authorization Rule field template:\n" + operationConfigAttribute.getAuditData() + "\n"
		                    + ". Check content into column 'Authorization Rule' of the table 'Adf Elementary Operation' for operation id " + operationConfigAttribute.getOperationId() + ". Probably the content is not a valid Velocity script language. Error:" + e.getLocalizedMessage());
		        }
			}
		}
		super.afterCompletion(request, response, handler, ex);
	}
}
