package itn.com.cmm.aspect;

import java.util.Enumeration;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;

import com.google.common.collect.Lists;

import itn.com.cmm.util.IpUtil;

@Component
public class LoggerAspect {
    private static final Logger log = LoggerFactory.getLogger(LoggerAspect.class);
    
    
    public Object methodLogger(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        try {
            StringBuffer logBuffer = new StringBuffer();
            List<Object> logList = Lists.newArrayList();
            
            
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); // request 정보를 가져온다.
            
            String controllerName = proceedingJoinPoint.getSignature().getDeclaringType().getSimpleName();
            String methodName = proceedingJoinPoint.getSignature().getName();
            logBuffer.append("\n┌ [●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● 요청정보 ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●]\n");
            logBuffer.append("│ [Method] URL : [{}] {}\n");
            logList.add(request.getMethod());
            logList.add(request.getRequestURI());

            logBuffer.append("│ Request IP : {}\n");
            logList.add(IpUtil.getClientIP(request));
            
            logBuffer.append("│ Request Browser : {}\n");
            logList.add(IpUtil.getBrowser(request));
            
            logBuffer.append("│ Controller : [{}] - [{}] \n");
            logList.add(controllerName);
            logList.add(methodName);
            
            logBuffer.append("│ 요청Param : {}\n");
            logList.add(getParams(request));
            
            long start = System.currentTimeMillis();
            
            
            Object result = proceedingJoinPoint.proceed();
            
            long end = System.currentTimeMillis();
            logBuffer.append("│ Time : [{}] sec\n");
            logList.add( (double)(end - start)/1000d );
            
            if( result instanceof ModelAndView ) {
                logBuffer.append("│ Result : {}\n");
                logList.add(result);
            }else if( result instanceof String ) {
                logBuffer.append("│ View : {}\n");
                logList.add(result);
            } else {
                logBuffer.append("│ Result : {}\n");
                logList.add(result);
            }
            
            proceedingJoinPoint.getArgs();
            
            logBuffer.append("└ [●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●]");
            if(result!=null && result.toString().indexOf("web/com")<0) {    // heder, footer, navi 로그는 찍지 않음. 
                log.info(logBuffer.toString(), logList.toArray());
            }
            
            return result;
            
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            throw throwable;
        }
    }
    
    /**
     * request 에 담긴 정보를 JSONObject 형태로 반환한다.
     * 
     * @param request
     * @return
     */
    @SuppressWarnings("unchecked")
    private static JSONObject getParams(HttpServletRequest request) {
        JSONObject jsonObject = new JSONObject();
        Enumeration<String> params = request.getParameterNames();
        while (params.hasMoreElements()) {
            String param = params.nextElement();
            String replaceParam = param.replaceAll("\\.", "-");
            jsonObject.put(replaceParam, request.getParameter(param));
        }
        return jsonObject;
    }
}
