package com.xmomen.module.system;

import com.xmomen.module.system.model.LogModel;
import com.xmomen.module.system.service.LogService;
import com.xmomen.module.logger.Log;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * Created by Jeng on 16/3/20.
 */
@Aspect
public class LoggerAspect {

    // 注入LogService
    @Autowired
    LogService logService;

    // 注入HttpServletRequest
    @Autowired
    HttpServletRequest request;

    /**
     * 日志逻辑切入点
     */
    @Pointcut("@annotation(com.xmomen.module.logger.Log)")
    public void getLogInfo() { }

    /**
     * 管理员添加操作日志(后置通知)
     * @param joinPoint
     * @throws Throwable
     */
    @AfterReturning(value = "getLogInfo()")
    public void afterReturning(JoinPoint joinPoint) throws Throwable{
        //获取登录用户名
        String username = (String) SecurityUtils.getSubject().getPrincipal();
        if(username == null){//没有管理员登录
            return;
        }
        //判断参数
        if(joinPoint.getArgs() == null){//没有参数
            return;
        }
        //获取方法名
        String methodName = joinPoint.getSignature().getName();
        Object target = joinPoint.getTarget();
        Method method = getMethodByClassAndName(target.getClass(), methodName);    //得到拦截的方法
        Object[] args = joinPoint.getArgs();     //方法的参数
        Log an = (Log)getAnnotationByMethod(method ,Log.class );
        if(an == null){
            return;
        }
        String actionName = an.actionName();
        //获取当前登录用户id
        Integer user_id =(Integer) SecurityUtils.getSubject().getSession().getAttribute("user_id");
        //创建日志对象
        LogModel log = new LogModel();
        log.setUserId(user_id);
        //设置管理员id
        log.setActionDate(new Date());
        //操作时间
        log.setActionResult(null);
        //操作内容
        log.setClientIp(getRemoteHost(request));
        log.setActionName(actionName);
        //操作
    /**
     * 根据方法获取注解
     * @param method
    //根据方法和方法注解类获取注解
     * @param annoClass
        //获取方法上的所有注解
     * @return
     */
        logService.insertLog(log);//添加日志
    }

    public Annotation getAnnotationByMethod(Method method , Class annoClass){
        // 获取方法上的所有注解
        Annotation all[] = method.getAnnotations();
        // 遍历所有注解
        for (Annotation annotation : all) {
            // 如果注解类型与传入的注解类型相同
            if (annotation.annotationType() == annoClass) {
                // 返回该注解
                return annotation;
    /**
     * 根据类和方法名获取方法
     * @param c
     * @param methodName
     * @return
     */
            }
        }
        return null;
    }

    // 根据类和名称获取方法
    public Method getMethodByClassAndName(Class c , String methodName){
        // 获取类的所有方法
        Method[] methods = c.getDeclaredMethods();
        // 遍历所有方法
        for (Method method : methods) {
            // 如果方法名称与传入的名称相同
            if(method.getName().equals(methodName)){
    /**
     * 获取客户端ip
     * @param request
     * @return
     */
                return method ;
            }
        }
        return null;
    }

        // 获取请求头中的x-forwarded-for字段，该字段表示客户端的IP地址
    public String getRemoteHost(javax.servlet.http.HttpServletRequest request){
        // 如果x-forwarded-for字段为空或者长度为0，或者值为unknown，则获取Proxy-Client-IP字段
        String ip = request.getHeader("x-forwarded-for");
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
            ip = request.getHeader("Proxy-Client-IP");
        // 如果Proxy-Client-IP字段为空或者长度为0，或者值为unknown，则获取WL-Proxy-Client-IP字段
        }
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
        // 如果ip为空或者长度为0或者等于"unknown"，则获取request的远程地址
        // 如果WL-Proxy-Client-IP字段为空或者长度为0，或者值为unknown，则获取request的remoteAddr属性
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        // 如果ip等于"0:0:0:0:0:0:0:1"，则返回"127.0.0.1"，否则返回ip
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
            ip = request.getRemoteAddr();
        }
        return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;
    }
}
