package gov.va.med.ars.spring.interceptor;

import java.sql.Timestamp;

import gov.va.med.ars.audit.AuditLogger;
import gov.va.med.ars.beans.AuditLog;
import gov.va.med.ars.exceptions.KnownThrowable;
import gov.va.med.ars.spring.dao.DbLogManagerDao;

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

import org.aopalliance.intercept.MethodInvocation;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

@Component
public class ArsInterceptor extends HandlerInterceptorAdapter {
	
	@Autowired
	private DbLogManagerDao dbLogManagerDao;
	static final Logger errorLogger = Logger.getLogger("errorLogger");
	static final Logger auditLogger = Logger.getLogger("auditLogger");
	
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception 
	{
		System.out.println("DownloadAttachmentInterceptor: REQUEST Intercepted for URI: "
				+ request.getRequestURI());
		
		int index=request.getRequestURI().lastIndexOf('/');
		String methodName = (request.getRequestURI().substring(index +1));
		
		
		long accessTime=-1;
		AuditLog auditLog = null;
		AuditLogger auditLogger = new AuditLogger();
		
		try
		{
	        accessTime  = System.currentTimeMillis();
			auditLog = createAuditLog(request, methodName, accessTime);

		}
		catch ( Exception e)
		{
			e.printStackTrace();
			auditLog = createAuditLog(request, methodName, accessTime);
			if ( e instanceof KnownThrowable)
			{
				throw e;
			}

		}
		finally
		{
			doAuditing(auditLog);
		}
		
		
		return true;
	}
	
	private void doAuditing(AuditLog auditLog)
	{
		try
		{
			if( dbLogManagerDao == null)
			{
				System.out.println("dbLogManagerDao is null");
			}
			else if ( auditLog == null )
			{
				System.out.println("auditLog is null");
			}
			
			dbLogManagerDao.logOperation(auditLog);
		}
		catch ( Exception e)
		{
			e.printStackTrace();
			logAuditToFile(auditLog);
		}
	}
	
	
	private void setRequestArgs(HttpServletRequest request,
								AuditLog auditLog) 
	{
		StringBuilder requestArgs = new StringBuilder();
		int claimAttachmentId = Integer.parseInt(request.getParameter("id"));
		if(claimAttachmentId != 0)
		{
			requestArgs.append("ClaimAttachmentId="+claimAttachmentId);
		}
		
		auditLog.setRequestArgs(requestArgs.toString());
	}
	
	
	private AuditLog createAuditLog(HttpServletRequest request, 
			                        String methodName,
			                        long accessTime) 
	{
		AuditLog auditLog = new AuditLog();	
		String action = "";
		
		auditLog.setAccessDate(new Timestamp(accessTime));
		setRequestArgs(request, auditLog);
				
		if( methodName.contains("download"))
		{
			action = "DOWNLOAD";
		}
		else if(methodName.contains("view") )
		{
			action = "VIEW";
		}
		else if(methodName.contains("save") )
		{
			action = "EDIT";
		}
		else if(methodName.contains("delete") )
		{
			action = "DELETE";
		}
				
		auditLog.setAction(action);
		//boolean success = ( returnValue instanceof Exception || returnValue instanceof KnownThrowable)?false:true;
		//auditLog.setSuccess(success);	
		int claimAttachmentId = Integer.parseInt(request.getParameter("id"));
		auditLog.setClaimAttachmentId(claimAttachmentId);
		auditLog.setMethodName(methodName);
		//auditLog.setUserId(System.getProperty("user.name"));
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
	    String userId = auth.getName().split("::")[0];
	    auditLog.setUserId(userId);
				
		return auditLog;
	}
	
	/**
	 * logs to the configured logger in a csv format for easier viewing and manipulation
	 * 
	 * @param auditLog
	 */
	private void logAuditToFile(AuditLog auditLog)
	{
		char separator = ',';
		
		StringBuilder s = new StringBuilder();
		
		s.append(""+auditLog.getMethodName()+separator);
		s.append(""+auditLog.getUserId()+separator);
		s.append(""+auditLog.getClaimAttachmentId()+separator);
		//s.append(""+auditLog.getLocalDateTime()+separator);
		s.append(""+auditLog.getAction()+separator);
		s.append(""+auditLog.getSuccess()+separator);
		s.append(""+auditLog.getAccessDate()+separator);
		s.append(""+auditLog.getVer()+separator);
		s.append(""+auditLog.getRequestArgs()+separator);
		
		String auditLine = s.toString();
		auditLogger.info(auditLine);
		
	}

}
