package com.cftech.sys.controller;

import com.alibaba.fastjson.JSONObject;
import com.cftech.core.annotation.CSRFTokenRef;
import com.cftech.core.config.MpGlobalConfig;
import com.cftech.sys.filter.McCsrfTokenRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 基于注解形式的返回拦截器
 * Created by Jasper Huang on 2018/6/5.
 */
@ControllerAdvice
public class McResponseBodyAnnoController implements ResponseBodyAdvice {
    private static Logger logger = LoggerFactory.getLogger(McResponseBodyAnnoController.class);
    @Autowired
    private McCsrfTokenRepository mcCsrfTokenRepository;
    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
            Method method = methodParameter.getMethod();
            if(method.isAnnotationPresent(CSRFTokenRef.class))
            {
//                RequestMapping rm = method.getAnnotation(RequestMapping.class);
                return true;
            }


        return false;
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        if (serverHttpRequest.getMethod() == HttpMethod.POST) {
            if (o instanceof JSONObject) {
                if (MpGlobalConfig.TOKEN_REFRESH) {
                    CsrfToken token = getCsrfToekn(serverHttpRequest,serverHttpResponse);
                    JSONObject rtnJson = (JSONObject) o;
                    rtnJson.put("_csrf_header", token.getHeaderName());
                    rtnJson.put("_csrf", token.getToken());
                    return rtnJson;
                }
            } else if (o instanceof net.sf.json.JSONObject) {
                if (MpGlobalConfig.TOKEN_REFRESH) {
                    CsrfToken token = getCsrfToekn( serverHttpRequest,serverHttpResponse);
                    net.sf.json.JSONObject rtnJson = (net.sf.json.JSONObject) o;
                    rtnJson.put("_csrf_header", token.getHeaderName());
                    rtnJson.put("_csrf", token.getToken());
                    return rtnJson;
                }
            } else if (o instanceof org.json.JSONObject) {
                CsrfToken token = getCsrfToekn(serverHttpRequest,serverHttpResponse);
                org.json.JSONObject rtnJson = (org.json.JSONObject) o;
                rtnJson.put("_csrf_header", token.getHeaderName());
                rtnJson.put("_csrf", token.getToken());
                return rtnJson;
            }
        }
        return o;
    }

    private CsrfToken getCsrfToekn(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse)
    {
        HttpServletRequest request = ((ServletServerHttpRequest)serverHttpRequest).getServletRequest();
        HttpServletResponse response = ((ServletServerHttpResponse)serverHttpResponse).getServletResponse();
        CsrfToken token = mcCsrfTokenRepository.generateTokenWithSave(request, response);
        return token;
    }
}
