package com.sy.coinage.core.aop.util;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import org.apache.ibatis.javassist.*;
import org.apache.ibatis.javassist.bytecode.CodeAttribute;
import org.apache.ibatis.javassist.bytecode.LocalVariableAttribute;
import org.apache.ibatis.javassist.bytecode.MethodInfo;
import org.aspectj.lang.JoinPoint;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

public class RequestUtil {

    public static final String CLASS_NAME = "className";

    public static final String METHOD_NAME = "methodName";

    public static final String USER = "user";

    public static final String PARAM = "param";

    /**
     * 获取切入点方法信息
     *
     * @param @param joinPoint
     * @param @return
     * @return Map<String, Object> 返回类型
     * @Title: getJoinpointInfoMap
     * @date 2019年5月20日 上午10:06:31
     */
    public static Map<String, Object> getJoinpointInfoMap(JoinPoint joinPoint) {

        Map<String, Object> joinPointInfo = new HashMap<String, Object>();
        // 获取路径名称
        String className = joinPoint.getTarget().getClass().getSimpleName();
        // 获取方法名称
        String methodName = joinPoint.getSignature().getName();
        // 添加到map中
        joinPointInfo.put(CLASS_NAME, className);
        joinPointInfo.put(METHOD_NAME, methodName);
        Class<?> clazz = null;
        CtMethod ctMethod = null;
        LocalVariableAttribute attr = null;
        int length = 0;
        int pos = 0;

        try {
            clazz = Class.forName(joinPoint.getTarget().getClass().getName());
            String clazzName = clazz.getName();
            ClassPool pool = ClassPool.getDefault();
            ClassClassPath classClassPath = new ClassClassPath(clazz);
            pool.insertClassPath(classClassPath);
            CtClass ctClass = pool.get(clazzName);
            ctMethod = ctClass.getDeclaredMethod(methodName);
            MethodInfo methodInfo = ctMethod.getMethodInfo();
            CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
            attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
            if (attr == null) {
                return joinPointInfo;
            }
            length = ctMethod.getParameterTypes().length;
            pos = Modifier.isStatic(ctMethod.getModifiers()) ? 0 : 1;
        } catch (Exception e) {
            e.printStackTrace();
        }
        String[] paramsArgsNames = new String[length];
        Object[] paramsArgsVlaues = joinPoint.getArgs();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            paramsArgsNames[i] = attr.variableName(i + pos);
            String paramsArgsName = attr.variableName(i + pos);
            if (paramsArgsName.equalsIgnoreCase("request") || paramsArgsName.equalsIgnoreCase("response")
                            || paramsArgsName.equalsIgnoreCase("session")) {
                break;
            }
            Object paramsArgsValue = paramsArgsVlaues[i];
            // 如果有操作用户 直接放map中
            if (paramsArgsName.equals(USER)) {
                joinPointInfo.put(USER, JSON.toJSONString(paramsArgsValue, JSONWriter.Feature.ReferenceDetection,
                                JSONWriter.Feature.WriteMapNullValue));
            } else {
                sb.append(JSON.toJSONString(paramsArgsValue, JSONWriter.Feature.ReferenceDetection,
                                JSONWriter.Feature.WriteMapNullValue));
            }

        }
        joinPointInfo.put(PARAM, sb.toString());
        return joinPointInfo;
    }

    /**
     * 获取请求方式 1：普通方式 2：ajax 方式
     *
     * @param @param request
     * @param @return
     * @param @throws Exception
     * @return Integer 返回类型
     * @Title: getRequestType
     * @date 2019年5月20日 上午10:44:46
     */
    public static Integer getRequestType(HttpServletRequest request) throws Exception {
        if (request == null) {
            throw new Exception("request对象为空");
        }
        String xRequestWith = request.getHeader("x-requested-with");

        return xRequestWith == null ? 1 : 2;

        /*
         * 判断ajax 请求方式 ： 异步请求 还是同步请求 if (request.getHeader("x-requested-with") != null &&
         * request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
         * System.out.println("该请求是 AJAX 异步HTTP请求。"); }else{ System.out.println("该请求是传统的 同步HTTP请求。"); }
         */
    }

    /**
     * - 获取请求ip
     *
     * @param @param request
     * @param @return
     * @return String 返回类型
     * @throws Exception
     * @Title: getRequestIp
     * @date 2019年5月20日 上午11:02:15
     */
    public static String getRequestIp(HttpServletRequest request) throws Exception {
        if (request == null) {
            throw new Exception("request 对象为空");
        }
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

}
