package kcc.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 kcc.com.cmm.util.IpUtil;

@Component
public class LoggerAspect {
    private static final Logger log = LoggerFactory.getLogger(LoggerAspect.class);


    public Object methodLogger(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        StringBuffer logBuffer = new StringBuffer();
        List<Object> logList = Lists.newArrayList();
        Object result = null;
        try {

            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();


             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
                    && result.toString().indexOf("main/inc")<0
                    ) {    // heder, footer, navi 로그는 찍지 않음.
                log.info(logBuffer.toString(), logList.toArray());
            }

            return result;

        } catch (Throwable throwable) {
            logBuffer.append("└ [●●●●●●●●●●●●●●●●●●●●●●●●●●●●]");
            log.info(logBuffer.toString(), logList.toArray());

            System.out.println("Throwable Log ::: "+ throwable.toString());
            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;
    }
}
