package com.zhiqiyun.open.utils;

import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Created on 2015年09月24
 * <p>
 * Title: Servlet上下文
 * </p>
 * <p>
 * Description: 获取请求上下文的request,response等信息
 * </p>
 * <p>
 * Copyright: Copyright (c) 2015
 * </p>
 *
 * @author jtoms
 * @version 1.0
 */
public class ServletContext {

    private final static String[] PROXY_REMOTE_IP_ADDRESS = {"x-forwarded-for", "proxy-client-ip", "wl-proxy-client-ip", "x-real-ip"};
    private final static String[] PROXY_ACCESS_TOKEN = {"x-header-access-token", "x-access-token"};
    private final static String[] PROXY_FROM_SOURCE = {"x-header-from-source", "x-from-source"};

    private final static ThreadLocal<ServletContext> CONTROLLER_CONTEXT = new ThreadLocal<>();

    private final static String REQUEST_ID = "____REQUEST_ID____";
    private final static String HTTP_SERVLET_REQUEST = "____HTTP_SERVLET_REQUEST____";
    private final static String HTTP_SERVLET_RESPONSE = "____HTTP_SERVLET_RESPONSE____";
    private final static String REMOTE_IP_ADDRESS = "____REMOTE_IP_ADDRESS____";
    private final static String ACCESS_TOKEN = "____ACCESS_TOKEN____";
    private final static String FORM_SOURCE = "____FORM_SOURCE____";
    private final static String IS_JSON = "____IS_JSON____";

    private final Map<String, Object> context;

    public ServletContext(Map<String, Object> context) {
        this.context = context;
    }

    /**
     * Created on 2015-09-24
     * <p>
     * Description:初始化 该方法在ControllerFilter中调用其他地方不能调用
     * </p>
     */
    public static void init(HttpServletRequest request, HttpServletResponse response) {
        CONTROLLER_CONTEXT.set(new ServletContext(new HashMap<>()));
        String requestId = UUID.randomUUID().toString();

        CONTROLLER_CONTEXT.get().getContext().put(REQUEST_ID, requestId);
        CONTROLLER_CONTEXT.get().getContext().put(HTTP_SERVLET_REQUEST, request);
        CONTROLLER_CONTEXT.get().getContext().put(HTTP_SERVLET_RESPONSE, response);
        CONTROLLER_CONTEXT.get().getContext().put(REMOTE_IP_ADDRESS, getRemoteIPAddress(request));
        CONTROLLER_CONTEXT.get().getContext().put(ACCESS_TOKEN, getAccessToken(request));
        CONTROLLER_CONTEXT.get().getContext().put(FORM_SOURCE, getFromSource(request));
        CONTROLLER_CONTEXT.get().getContext().put(IS_JSON, isJson(request));
    }

    public static void clean() {
        CONTROLLER_CONTEXT.set(null);
        CONTROLLER_CONTEXT.remove();
    }

    /**
     * Created on 2015-09-24
     * <p>
     * Description:获取 request
     * </p>
     */
    public static HttpServletRequest getRequest() {
        return getValue(HTTP_SERVLET_REQUEST);
    }

    public static boolean isJson() {
        return getValue(IS_JSON);
    }

    public static HttpServletResponse getResponse() {
        return getValue(HTTP_SERVLET_RESPONSE);
    }

    @SuppressWarnings("unchecked")
    public static <T> T getValue(String key) {
        return (T) CONTROLLER_CONTEXT.get().getContext().get(key);
    }

    public static void set(String key, Object value) {
        CONTROLLER_CONTEXT.get().getContext().put(key, value);
    }

    public static String getFromSource() {
        return getValue(FORM_SOURCE);
    }

    public static String getRequestId() {
        return getValue(REQUEST_ID);
    }

    public static String getRemoteIPAddress() {
        return getValue(REMOTE_IP_ADDRESS);
    }

    public static String getAccessToken() {
        return getValue(ACCESS_TOKEN);
    }

    public static String getAccessToken(HttpServletRequest request) {
        return getHeaderValue(request, PROXY_ACCESS_TOKEN);
    }

    public static String getFromSource(HttpServletRequest request) {
        return getHeaderValue(request, PROXY_FROM_SOURCE);
    }

    public static Map<String, String> getRequestParamMap() {
        HttpServletRequest request = getRequest();
        Enumeration<String> parameterNames = request.getParameterNames();

        Map<String, String> dataMap = new HashMap<>();
        while (parameterNames.hasMoreElements()) {
            String key = parameterNames.nextElement();
            String value = request.getParameter(key);
            dataMap.put(key, value);
        }
        return dataMap;
    }

    public static String getRemoteIPAddress(HttpServletRequest request) {
        String xforwardIp = getHeaderValue(request, PROXY_REMOTE_IP_ADDRESS);
        if (StringUtils.isNotBlank(xforwardIp)) {
            return getRemoteIpFromForward(xforwardIp);
        } else {
            return request.getRemoteHost();
        }
    }

    public static String getHeaderValue(HttpServletRequest request, String[] nameArrays) {
        String value = "";
        for (String s : nameArrays) {
            value = request.getHeader(s);
            if (StringUtils.isNotBlank(value)) {
                break;
            }
        }
        return value;
    }

    /**
     * <p>
     * 从 HTTP Header 的 X-Forward-IP 头中截取客户端连接 IP 地址。如果经过多次反向代理， 在 X-Forward-IP
     * 中获得的是以“,&lt;SP&gt;”分隔 IP 地址链，第一段为客户端 IP 地址。
     * </p>
     *
     * @param xforwardIp
     * @return
     */
    private static String getRemoteIpFromForward(String xforwardIp) {
        int commaOffset = xforwardIp.indexOf(',');
        if (commaOffset < 0) {
            return xforwardIp;
        }
        return xforwardIp.substring(0, commaOffset);
    }


    /**
     * 判断本次请求的数据类型是否为json
     *
     * @param request request
     * @return boolean
     */
    private static boolean isJson(HttpServletRequest request) {
        String contentType = request.getContentType();
        return StringUtils.contains(contentType, "application/json");
    }

    private Map<String, Object> getContext() {
        return context;
    }

}
