package com.pingpang.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FileUtils;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
import org.lionsoul.ip2region.DbSearcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ResourceUtils;

public class IPUtil {
	
	// 日志操作
    protected static Logger logger = LoggerFactory.getLogger(IPUtil.class);
	
	/** 
	 * 获得客户端真实IP地址 
	 * @[author]param[/author] request 
	 * @return 
	 */ 
	public static String getIpAddr(HttpServletRequest request) { 
	   String ip = request.getHeader("X-Forwarded-For");
	   ip = getTrueIp(ip);
		    	
	   if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	       ip = request.getHeader("Proxy-Client-IP");
	       ip = getTrueIp(ip);
	   }
	   if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	       ip = request.getHeader("WL-Proxy-Client-IP");
	       ip = getTrueIp(ip);
	   }
	   if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	       ip = request.getHeader("HTTP_CLIENT_IP");
	       ip = getTrueIp(ip);
	   }
	   if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	       ip = request.getHeader("HTTP_X_FORWARDED_FOR");
	       ip = getTrueIp(ip);
	   }
	   if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	      ip = request.getRemoteAddr();
	      ip = getTrueIp(ip);
	   }
	      return ip; 
	}


	/**
	 * 取真实客户端IP，过滤代理IP
	 * @[author]param[/author] ip
	 * @return
	 */
	public static String getTrueIp(String ip){
	   if(ip == null || "".equals(ip))return null;
	   if(ip.indexOf(",") != -1){
	       String[] ipAddr = ip.split(",",-1);
	       for(int i=0; i<ipAddr.length; i++){
	          if(isIp(ipAddr[i].trim()) && !ipAddr[i].trim().startsWith("10.")
	             && !ipAddr[i].trim().startsWith("172.16")){
	             return ipAddr[i].trim();
	          } 
	       }
	   }else{
	       if(isIp(ip.trim()) && !ip.trim().startsWith("10.")
	          && !ip.trim().startsWith("172.16"))
	          return ip.trim();
	   }
	   return null;
	}
	
	 /**
                * 判断所有的IP地址
      * @param IP
      * @return
      */
    public static boolean isIp(String IP) {
 
        if (!IP.contains(".") && !IP.contains(":")) {
            return false;
        }
        //如果是IPV4
        if (IP.contains(".")) {
            if (IP.endsWith(".")) {
                return false;
            }
            String[] arr = IP.split("\\.");
            if (arr.length != 4) {
                return false;
            }
 
            for (int i = 0; i < 4; i++) {
                if (arr[i].length() == 0 || arr[i].length() > 3) {
                    return false;
                }
                for (int j = 0; j < arr[i].length(); j++) {
                    if (arr[i].charAt(j) >= '0' && arr[i].charAt(j) <= '9') {
                        continue;
                    }
                    return false;
                }
                if (Integer.valueOf(arr[i]) > 255 || (arr[i].length() >= 2 && String.valueOf(arr[i]).startsWith("0"))) {
                    return false;
                }
            }
            return true;
        }//如果是IPV4
 
        //如果是IPV6
        if (IP.contains(":")) {
            if (IP.endsWith(":") && !IP.endsWith("::")) {
                return false;
            }
            //如果包含多个“::”，一个IPv6地址中只能出现一个“::”
            if (IP.indexOf("::") != -1 && IP.indexOf("::", IP.indexOf("::") + 2) != -1) {
                return false;
            }
 
            //如果含有一个“::”
            if (IP.contains("::")) {
                String[] arr = IP.split(":");
                if (arr.length > 7 || arr.length < 1) {//"1::"是最短的字符串
                    return false;
                }
                for (int i = 0; i < arr.length; i++) {
                    if (arr[i].equals("")) {
                        continue;
                    }
                    if (arr[i].length() > 4) {
                        return false;
                    }
                    for (int j = 0; j < arr[i].length(); j++) {
                        if ((arr[i].charAt(j) >= '0' && arr[i].charAt(j) <= '9') || (arr[i].charAt(j) >= 'A' && arr[i].charAt(j) <= 'F')
                                || (arr[i].charAt(j) >= 'a' && arr[i].charAt(j) <= 'f')) {
                            continue;
                        }
                        return false;
                    }
                }
                return true;
            }
 
            //如果不含有“::”
            if (!IP.contains("::")) {
                String[] arr = IP.split(":");
                if (arr.length != 8) {
                    return false;
                }
                for (int i = 0; i < arr.length; i++) {
                    if (arr[i].length() > 4) {
                        return false;
                    }
                    for (int j = 0; j < arr[i].length(); j++) {
                        if ((arr[i].charAt(j) >= '0' && arr[i].charAt(j) <= '9') || (arr[i].charAt(j) >= 'A' && arr[i].charAt(j) <= 'F')
                                || (arr[i].charAt(j) >= 'a' && arr[i].charAt(j) <= 'f')) {
                            continue;
                        }
                        return false;
                    }
                }
                return true;
            }
        }//如果是IPV6
        return false;
    }
    
//---------------------------IP统计-------------------------------------------
    private static final String UNKOWN_ADDRESS = "";

    /**
     * 根据IP获取地址
     *
     * @return 国家|区域|省份|城市|ISP
     */
    public static String getAddress(String ip,String targePath) {
        return getAddress(ip, DbSearcher.BTREE_ALGORITHM, targePath);
    }

    /**
     * 根据IP获取地址
     *
     * @param ip
     * @param algorithm 查询算法
     * @return 国家|区域|省份|城市|ISP
     * @see DbSearcher
     * DbSearcher.BTREE_ALGORITHM; //B-tree
     * DbSearcher.BINARY_ALGORITHM //Binary
     * DbSearcher.MEMORY_ALGORITYM //Memory
     */
    public static String getAddress(String ip, int algorithm,String targetPath) {
     try {	
        if (!IPUtil.isIp(ip)) {
        	logger.error("错误格式的ip地址: {}", ip);
            return UNKOWN_ADDRESS;
        }
        //String dbPath = IPUtil.class.getResource("/ip2region.db").getPath();
        //String dbPath="D:\\ChatWork\\PingPangChat\\PingPangChat\\PingPangDB\\src\\main\\resources\\ip2region.db";
        //String dbPath=IPUtil.class.getResource("/ip2region.db").getPath();
        //File file = ResourceUtils.getFile("classpath:ip2region.db");
//        ClassPathResource classPathResource = new ClassPathResource("ip2region.db");
//        File sourceFile = classPathResource.getFile();
//        if (!sourceFile.exists()) {
//        	logger.error("地址库文件不存在");
//            return UNKOWN_ADDRESS;
//        }
        File sourceFile = new File(targetPath+"ip2region.db");
        logger.info("IPDB:"+targetPath+"ip2region.db");
        
        if (!sourceFile.exists()) {
        	copyFile("/ip2region.db",targetPath+"ip2region.db");
        }
        
        DbSearcher searcher = new DbSearcher(new DbConfig(),targetPath+"ip2region.db");
        DataBlock dataBlock;
        switch (algorithm) {
            case DbSearcher.BTREE_ALGORITHM:
                dataBlock = searcher.btreeSearch(ip);
                break;
            case DbSearcher.BINARY_ALGORITHM:
                dataBlock = searcher.binarySearch(ip);
                break;
            case DbSearcher.MEMORY_ALGORITYM:
                dataBlock = searcher.memorySearch(ip);
                break;
            default:
            	logger.error("未传入正确的查询算法");
                return UNKOWN_ADDRESS;
        }
        return dataBlock.getRegion();
     }catch(Exception e) {
    	 logger.error("获取IP出错", e);
     }
     return UNKOWN_ADDRESS;
    }
    
	/**
	 * 将jar包的文件复制到能读取的地方
	 * @param src
	 * @param targets
	 * @throws IOException
	 */
	public static void copyFile(String src,String target) throws IOException {
		ClassPathResource classPathResource = new ClassPathResource(src);
		InputStream inputStream =classPathResource.getInputStream();
		File docxFile = new File(target);
        // 使用common-io的工具类即可转换
        FileUtils.copyInputStreamToFile(inputStream,docxFile);
        inputStream.close();
	}
    
    public static void main(String[] args) {
//    	System.out.println(IPUtil.getAddress("119.118.179.94"));
//        System.out.println(IPUtil.getAddress("27.38.243.145"));
//        System.out.println(IPUtil.getAddress("218.195.219.255"));
//        System.out.println(IPUtil.getAddress("116.37.161.86"));
//        System.out.println(IPUtil.getAddress("136.27.231.86"));
//        System.out.println(IPUtil.getAddress("127.0.0.1"));
//        System.out.println(IPUtil.getAddress("112.17.236.511"));
	}
}
