package com.chinacreator.video.util;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import com.chinacreator.video.bean.OrderInfo;
import com.chinacreator.video.mapper.DictionaryDao;

/**
 * 获取IP地址
 * @author xu.zhou
 * @date 20210426
 */
public class IpAddrUtil {
	
	private static Logger logger = Logger.getLogger("testredis");
	
	/***
	 * 阿里云IP地址，共有两个
	 * remote_addr":"8.140.139.5"
	 * remote_addr":"47.94.198.208"
	 */
	private static List<String> aliips = new ArrayList<String>();
	static{
		aliips.add("8.140.139.5");
		aliips.add("47.94.198.208"); 
	}
	
	/**
	 * 输出IP地址信息
	 * @param request
	 */
	private static StringBuffer printHeader(HttpServletRequest request, String channel){
		StringBuffer sb = new StringBuffer();
		//sb.append("==============渠道=>"+channel+", header信息==============\r\n");
		//logger.info("remoteaddr=>"+request.getRemoteAddr());
		sb.append("name=>remoteaddr, value=>"+request.getRemoteAddr()+"\r\n");
		Enumeration er = request.getHeaderNames();//获取请求头的所有name值
		while(er.hasMoreElements()){
			String name	=(String) er.nextElement();
			String value = request.getHeader(name);
			sb.append("name=>"+name+", value=>"+value+"\r\n");
		}

		//logger.info("\r\n================渠道=>"+channel+"的header信息=>\r\n"+sb.toString());
		return sb;
	}
	
	/**
	 * 获取请求的所有IP
	 * @param request 
	 * @param orderInfo 请求参数
	 * @param remoteAddrChannel rmoteaddr允许取值渠道，多个用英文逗号分隔
	 * @return
	 */
	public static List<String> getIpAddrs(HttpServletRequest request, OrderInfo orderInfo, String remoteAddrChannel) {
		StringBuffer sb = printHeader(request, orderInfo.getChannel());
		//先获取真实IP，但经过阿里云域名过来的得到是阿里云的IP 
		List<String> ipList = getHeaderIps(request, orderInfo.getChannel(), remoteAddrChannel);
	    sb.append("渠道=>"+orderInfo.getChannel()+"，接口=>"+request.getHeader("x-forwarded-path")+"，最终获取的IP为=>"+ipList);
		sb.append("==============================\r\n");
	    logger.info("\r\n================渠道=>"+orderInfo.getChannel()+"的header信息=>\r\n"+sb.toString());
	    return ipList;
	}
	 
	 /***
	  * 到请求头获取所有IP地址
	  * @param request
	  * @param channel 调用渠道标识
	  * @param remoteAddrChannel 需要取remoteAddr的IP的渠道
	  * @return
	  */
	 public static List<String> getHeaderIps(HttpServletRequest request, String channel, String remoteAddrChannel) {
		 List<String> ipList = new ArrayList<String>();
		 addIps(ipList,request.getHeader("X-Forwarded-For"));
		 addIps(ipList,request.getHeader("X-Real-IP"));
		 addIps(ipList,request.getHeader("Proxy-Client-IP"));	
	 	 addIps(ipList,request.getHeader("WL-Proxy-Client-IP"));
	 	 addIps(ipList,request.getHeader("clientip"));
	 	 //是否有限制取remoteaddr的渠道
	 	 if(StringUtils.isNotEmpty(remoteAddrChannel)){
	 		String [] arrayconf = remoteAddrChannel.split(",");
	 		for(String tmp : arrayconf){
	 			if(StringUtils.isNotEmpty(tmp) && tmp.equals(channel)){
	 				//只有配置的渠道才查询RemoteAddr值，当前只有CAP
	 				addIps(ipList,request.getRemoteAddr());
	 				break;
	 			}
	 		}
	 	 }else{//没有限制，所有调用渠道都取remoteaddr
	 		addIps(ipList,request.getRemoteAddr());
	 	 }

		 return ipList;
	 }
	 
	 /**
	  * 添加IP到List，重复IP不添加
	  * @param ipList
	  * @param getip
	  */
	 private static void addIps(List<String> ipList, String getip){
		 //IP不能为空
		 if(StringUtils.isNotEmpty(getip)){
			 //可能有多个IP，用,分隔
			 String [] arrayip = getip.split(",");
			 for(String tmp : arrayip){
				 if(StringUtils.isNotEmpty(tmp) 
						 && StringUtils.isNotEmpty(tmp.trim())
						 && !ipList.contains(tmp.trim())){
					 //添加数据，重复不添加
					 ipList.add(tmp.trim());
				 }
			 }
		 }
	 }
	
	/**
	 * 获取调用接口的真实IP地址
	 * @param request
	 * @param orderInfo
	 * @return
	 */
	public static String getIpAddr2(HttpServletRequest request, OrderInfo orderInfo) {
		printHeader(request, orderInfo.getChannel());
		return getIpAddr2(request, orderInfo.getChannel());
	}
	
	 /***
	  * 取IP地址新方式，判断是否从阿里云转发过来的
	  * 阿里云的IP地址共有两个 ，分别为8.140.139.5和47.94.198.208，放在remote_addr属性值内，
	  * 先取X-Real-IP值，判断是否为阿里云的IP，如果是则取X-Forwarded-For的第一个IP
	  * @param request
      * @param channel 渠道标识，用于记录日志	  
	  * @return
	  */
	 public static String getIpAddr2(HttpServletRequest request, String channel) {
		//先获取真实IP，但经过阿里云域名过来的得到是阿里云的IP 
	    String ip = getIpAddr2(request);
	    logger.info("渠道=>"+channel+"，接口=>"+request.getHeader("x-forwarded-path")+"，最终获取的IP为=>"+ip);
	    return ip;
	 }
	 
	 /**
	  * 
	  * @param request
	  * @return
		name=>remoteaddr, value=>10.0.17.54
		name=>host, value=>10.0.17.82:9999
		name=>connection, value=>keep-alive
		name=>x-forwarded-for, value=>111.206.133.53, 8.140.139.5, 10.0.17.29
		name=>x-forwarded-proto, value=>http
		name=>x-forwarded-host, value=>testapi.mige.tv
		name=>x-forwarded-port, value=>6060
		name=>x-forwarded-path, value=>/univideo/backorder
		name=>x-forwarded-prefix, value=>/univideo
		name=>x-real-ip, value=>10.0.17.29
		name=>content-length, value=>190
		name=>content-type, value=>application/x-www-form-urlencoded; charset=UTF-8
		name=>user-agent, value=>Apache-HttpClient/4.5.5 (Java/1.8.0_162)
		name=>accept-encoding, value=>gzip,deflate
		name=>set-cookie, value=>HttpOnly
		name=>x-frame-options, value=>SAMEORIGIN
	  */
	 public static String getIpAddr2(HttpServletRequest request) {
		//先获取X-Real-IP，正常的IP是放在这个属性，但经过阿里云域名过来的得到是阿里云的IP 
	    String ip = request.getHeader("X-Real-IP");
	    if (!inValidateIpAddr2(ip)) {
		    //如果是阿里云IP
		    if (aliips.contains(ip)){
		    	//取X-Forwarded-For的IP地址，有两个，比如39.101.199.87, 8.140.139.5
		    	ip = request.getHeader("X-Forwarded-For");
			    if(ip != null && !"".equals(ip.trim())){
			    	//取第一个
			    	ip = ip.trim().split(",")[0].trim();
			    }
	    	}else{
	    		//测试环境 ：42.192.87.194, 47.94.198.208, 10.0.17.29
	    		//生产环境：111.206.133.53, 111.206.133.53, 8.140.139.5
	    		//走阿里云的X-Forwarded-For有三个IP, 中间的IP是阿里的或第三个阿里云的， X-Real-IP得到的IP是10.0.17.29，不是真实IP，要取X-Forwarded-For第一个
	    		String xffip = request.getHeader("X-Forwarded-For");
			    if(StringUtils.isNotEmpty(xffip) && xffip.trim().split(",").length == 3 
			    		&& (aliips.contains(xffip.trim().split(",")[1].trim()) || aliips.contains(xffip.trim().split(",")[2].trim()))){
			    	//取第一个
			    	ip = xffip.trim().split(",")[0].trim();
			    }else{
			    	ip = ""; //ip设置为空，重新获取IP
			    }
	    	}
	    }
	    if (inValidateIpAddr2(ip)) {
		    ip = request.getHeader("X-Forwarded-For");
		}
	    if (inValidateIpAddr2(ip)) {
		    ip = request.getHeader("X-Real-IP");
		}
	    if (inValidateIpAddr2(ip)) {
	    	ip = request.getHeader("Proxy-Client-IP");
	    }
	    if (inValidateIpAddr2(ip)) {
	    	ip = request.getHeader("WL-Proxy-Client-IP");
	    }
	    if (inValidateIpAddr2(ip)) {
	    	ip = request.getHeader("clientip");
	    }
	    if (inValidateIpAddr2(ip)) {
	    	ip = request.getRemoteAddr();
	    }
	    if (inValidateIpAddr2(ip)) {
	    	ip = "null";
	    } else {
	    	int index = ip.indexOf(",");
	    	if (index != -1) {
	    		ip = ip.substring(0, index);
	    	}
	    }
	    
	    return ip;
	 }
	
	 /***
	  * 取IP地址新方式，判断是否从阿里云转发过来的
	  * 阿里云的IP地址共有两个 ，分别为8.140.139.5和47.94.198.208，放在remote_addr属性值内，
	  * 先取remote_addr值，判断是否为阿里云的IP，如果是再走之后的判断流程。
	  * @param request
	  * @return
	  */
	 /****
	 public static String getIpAddr220210616(HttpServletRequest request) {
	    String ip = request.getRemoteAddr();//先获取remoteaddr属性值
	    //如果是阿里云IP
	    if (ips.contains(ip)){
		    ip = request.getHeader("X-Real-IP");
		    if (inValidateIpAddr2(ip)) {
		      ip = request.getHeader("X-Forwarded-For");
		      if(ip != null && !"".equals(ip.trim())){
		    	  //X-Forwarded-For可能有两个IP，取第一个，比如：
		    	  ip = ip.trim().split(",")[0].trim();
		      }
		    }
		    if (inValidateIpAddr2(ip)) {
		      ip = request.getHeader("Proxy-Client-IP");
		    }
		    if (inValidateIpAddr2(ip)) {
		      ip = request.getHeader("WL-Proxy-Client-IP");
		    }
		    if (inValidateIpAddr2(ip)) {
		      ip = request.getHeader("clientip");
		    }
	    } else {//不是阿里云的IP
		    ip = request.getHeader("X-Real-IP");
		    if (inValidateIpAddr2(ip)) {
		      ip = request.getHeader("X-Forwarded-For");
		      if(ip != null && !"".equals(ip.trim())){
		    	  //X-Forwarded-For可能有两个IP，取第一个，比如：
		    	  ip = ip.trim().split(",")[0].trim();
		      }
		    }
		    if (inValidateIpAddr2(ip)) {
		      ip = request.getHeader("Proxy-Client-IP");
		    }
		    if (inValidateIpAddr2(ip)) {
		      ip = request.getHeader("WL-Proxy-Client-IP");
		    }
		    if (inValidateIpAddr2(ip)) {
		      ip = request.getHeader("clientip");
		    }
		    if (inValidateIpAddr2(ip)) {
		      ip = request.getRemoteAddr();
		    }
	    }	 

	    if (inValidateIpAddr2(ip)) {
	    	ip = "null";
	    } else {
		    int index = ip.indexOf(",");
		    if (index != -1) {
		       ip = ip.substring(0, index);
		    }
	    }
	    logger.info(request.getHeader("x-forwarded-path")+"=>最终获取的IP为："+ip);
	    return ip;
	 }
	 *****/
	
	 /**
	  * 取IP地址旧方法
	  * @param request
	  * @return
	  */
	 /******
	 public static String getIpAddr2_bak(HttpServletRequest request) {
		    String ip = request.getHeader("X-Real-IP");
		    if (inValidateIpAddr2(ip)) {
		      ip = request.getHeader("X-Forwarded-For");
		    }
		    if (inValidateIpAddr2(ip)) {
		      ip = request.getHeader("Proxy-Client-IP");
		    }
		    if (inValidateIpAddr2(ip)) {
		      ip = request.getHeader("WL-Proxy-Client-IP");
		    }
		    if (inValidateIpAddr2(ip)) {
		      ip = request.getHeader("clientip");
		    }
		    if (inValidateIpAddr2(ip)) {
		      ip = request.getRemoteAddr();
		    }
		    if (inValidateIpAddr2(ip)) {
		      ip = "null";
		    } else {
		      int index = ip.indexOf(",");
		      if (index != -1) {
		        ip = ip.substring(0, index);
		      }
		    }
		    return ip;
	 }
     *****/
     		
     private static boolean inValidateIpAddr2(String ip) {
		  return (ip == null) || (ip.length() == 0) || ("unknown".equalsIgnoreCase(ip));
    }	


	public static String getIpAddr(HttpServletRequest request) {
		String ip = request.getHeader("X-Real-IP");
		if (inValidateIpAddr(ip)) {
			ip = request.getHeader("X-Forwarded-For");
		}
		if (inValidateIpAddr(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (inValidateIpAddr(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (inValidateIpAddr(ip)) {
			ip = request.getHeader("clientip");
		}
		if (inValidateIpAddr(ip)) {
			ip = request.getRemoteAddr();
		}
		if (inValidateIpAddr(ip)) {
			ip = "null";
		} else {
			int index = ip.indexOf(",");
			if (index != -1) {
				ip = ip.substring(0, index);
			}
		}
		return ip;
	}

	
	/**
	 * ip地址是否有效
	 * 
	 * @param ip
	 * @return true：无效，false有效
	 */
	private static boolean inValidateIpAddr(String ip) {
		//System.out.println(ip);
		return ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)  || ip.startsWith("172.") || ip.startsWith("192.");
	}
	
	public static String getHostIp() {
		try {
			Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
			while (en.hasMoreElements()) {
				NetworkInterface intf = (NetworkInterface) en.nextElement();
				Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses();
				while (enumIpAddr.hasMoreElements()) {
					InetAddress inetAddress = (InetAddress) enumIpAddr.nextElement();
					if (!inetAddress.isLoopbackAddress() && !inetAddress.isLinkLocalAddress() && inetAddress.isSiteLocalAddress()) {
						return inetAddress.getHostAddress().toString();
					}
				}
			}
		} catch (SocketException e) {
			e.printStackTrace();
		}
		return null;
	}
}