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

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

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 it.mice.voila.runtime.entity.OperationLogMessage;
import it.mice.voila.runtime.security.OperationAuditService;
import it.mice.voila.runtime.security.OperationConfigAttribute;
import it.mice.voila.runtime.security.SecurityUtils;
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 OperationAuditServiceImpl implements OperationAuditService {
	/**
	 * default logger.
	 */
	Log log = LogFactory.getLog(OperationAuditServiceImpl.class);
	
	@Autowired
    private VelocityEngine velocityEngine;


	public void audit(OperationConfigAttribute operationConfigAttribute) {
		audit(operationConfigAttribute, null);
	}

	public void audit(OperationConfigAttribute operationConfigAttribute, Object form) {
		audit(operationConfigAttribute, form, null);
	}

	/* (non-Javadoc)
	 * @see it.mice.voila.runtime.springmvc.security.OperationAuditSecurity#audit(it.mice.voila.runtime.security.OperationConfigAttribute, java.lang.Object)
	 */
	public void audit(OperationConfigAttribute operationConfigAttribute, Object form, String userName) {

		if (operationConfigAttribute == null) {
			return;
		}
		if (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(userName != null ? userName : 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());
	        }
		}
	}
}
