package com.trs.web2frame.util;

//import com.google.common.base.Charsets;
import org.apache.commons.collections.map.MultiValueMap;
import org.apache.commons.io.FileUtils;
//import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang.StringUtils;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author Channing.Qiu
 * @date 2020/2/21 13:56
 */
public class Annex {

    private static String REGX_RELATIVE_PATH = "((\\\\)[\\u4e00-\\u9fa5\\w]+)+\\.([\\u4e00-\\u9fa5\\w]){1,4}";
    private static String REGX_DOMAIN_PATH = "[a-zA-Z^ ]{0,4}://([a-zA-Z]+\\.){2,4}[^ ^.]*\\.([a-zA-Z]){0,4}";
    private static String REGX_IP_PATH = "[a-zA-Z^ ]{0,4}://([0-9]+\\.){3}[0-9]{1,3}[^ ^.]*\\.([a-zA-Z]){0,4}";
    private static Pattern PATTERN_RELATIVE_PATH = Pattern.compile(REGX_RELATIVE_PATH);
    private static Pattern PATTERN_DOMAIN_PATH = Pattern.compile(REGX_DOMAIN_PATH);
    private static Pattern PATTERN_IP_PATH = Pattern.compile(REGX_IP_PATH);

    private static Map<Integer, Pattern> patternMap;

    private MultiValueMap fileInfo= new MultiValueMap();

    private static String FETCHED_FOLDER="fetched"+System.currentTimeMillis();
    private static String NEED_DIFF_FILE="diff"+System.currentTimeMillis();

    private List<String> addrList;

    public Annex(){
        patternMap = new HashMap<>();
        patternMap.put(1,PATTERN_RELATIVE_PATH);
        patternMap.put(2,PATTERN_DOMAIN_PATH);
        patternMap.put(3,PATTERN_IP_PATH);

        addrList = new ArrayList<>();
    }

    public Annex(String rootPath){
        this();
        traverseFolder(rootPath);
    }
    public Annex(String rootPath,String... addr){
        this(rootPath);
        addrList.addAll(Arrays.stream(addr).collect(Collectors.toList()));
    }

    public List<HandleResult> handle(String content){
        return parse(content);
    }

    public List<HandleResult> parse(String content){
        List<HandleResult> result = new ArrayList<>();

        patternMap.forEach((type, pattern) -> {
            Matcher m = pattern.matcher(content);
            while (m.find()) {
                String target = m.group();
                //System.out.println("target name:"+getFileName(target));
                if (fileInfo.containsKey(getFileName(target))) {
                    Collection values = fileInfo.getCollection(getFileName(target));
                    if(values.size()==1) {
                        result.add(new HandleResult().setType(type).setStatus(0)
                                .setPath(values.toArray()[0].toString()).setMessage("success"));
                    }else {
                        values.forEach(o -> {
                            
                            try {
                                FileUtils.writeStringToFile(null, target+" :"+o.toString()+"\n", "UTF_8");
                                //FileUtils.write(new File(NEED_DIFF_FILE),target+" :"+o.toString()+"\n", Charsets.UTF_8,true);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        });
                        result.add(new HandleResult().setType(type).setStatus(-1)
                                .setPath(target).setMessage("duplicate files"));
                    }
                }else if(1 == type){
                    result.add(new HandleResult().setType(type).setStatus(-1)
                            .setPath(m.group()).setMessage("file not found"));
                }else {
                    String addr = getAddr(target);
                    if((2==type && isInnerIP(domain2ip(addr)))
                    || (3==type && isInnerIP(addr))){
                        result.add(new HandleResult().setType(type).setStatus(-1)
                                .setPath(target).setMessage("file not found"));
                    }else if(2==type && addrList.contains(domain2ip(addr))
                    || (3==type && addrList.contains(addr))){
                        try {
                            String dest = String.join(File.separator
                                    , FETCHED_FOLDER, getFileName(target));
                            FileUtils.copyURLToFile(new URL(target), new File(dest));
                            fileInfo.put(getFileName(target),dest);
                            result.add(new HandleResult().setType(type).setStatus(0)
                                    .setPath(dest).setMessage("success"));
                        } catch (IOException e) {
                            result.add(new HandleResult().setType(type).setStatus(-1)
                                    .setPath(target).setMessage("file not found"));
                            System.out.println("failed loading file form net :" + target);
                        }
                    }else{
                        result.add(new HandleResult().setType(type).setStatus(0)
                                .setPath(target).setMessage("3rd net file"));
                    }
                }
            }
        });

        return result;
    }

    public String domain2ip(String domain){
        InetAddress myServer = null;
        try {
            myServer = InetAddress.getByName(domain);
        } catch (UnknownHostException e) {
            e.printStackTrace();
            System.out.println("can not get ip of domain:"+domain+"ex:"+e);
        }

        if(Objects.isNull(myServer)) return "";
        return myServer.getHostAddress();
    }

    private String getFileName(String path){
        return path.substring(Math.max(path.lastIndexOf("/"),path.lastIndexOf("\\"))+1);
    }
    private String getAddr(String url){
        return url.split("/")[2].split(":")[0];
    }

    private void traverseFolder(String path) {

        File file = new File(path);

        if(!file.exists()){
            System.out.println("file not exists!");
            return;
        }

        File[] files = file.listFiles();
        if (null == files || files.length == 0) {
            System.out.println("empty folder");
            return;
        }

        for (File subFile : files) {
            if (subFile.isDirectory()) {
                traverseFolder(subFile.getAbsolutePath());
            } else {
                System.out.println("file["+subFile.getName()+"]:" + subFile.getAbsolutePath());
                fileInfo.put(subFile.getName(),subFile.getAbsolutePath());
            }
        }
    }

    public boolean isInnerIP(String ipAddress){
        boolean isInnerIp;
        if (StringUtils.isEmpty(ipAddress)) return false;
        long ipNum = getIpNum(ipAddress);

        long aBegin = getIpNum("10.0.0.0");
        long aEnd = getIpNum("10.255.255.255");
        long bBegin = getIpNum("172.16.0.0");
        long bEnd = getIpNum("172.31.255.255");
        long cBegin = getIpNum("192.168.0.0");
        long cEnd = getIpNum("192.168.255.255");
        isInnerIp = isInner(ipNum,aBegin,aEnd) || isInner(ipNum,bBegin,bEnd) || isInner(ipNum,cBegin,cEnd) || ipAddress.equals("127.0.0.1");
        return isInnerIp;
    }

    private long getIpNum(String ipAddress) {
        String [] ip = ipAddress.split("\\.");
        long a = Integer.parseInt(ip[0]);
        long b = Integer.parseInt(ip[1]);
        long c = Integer.parseInt(ip[2]);
        long d = Integer.parseInt(ip[3]);

        return a * 256 * 256 * 256 + b * 256 * 256 + c * 256 + d;
    }

    private boolean isInner(long userIp,long begin,long end){
        return (userIp>=begin) && (userIp<=end);
    }

    public static void main(String[] args) {
        Annex annex = new Annex("G:\\gongsipeixun","60.11.11.22","60.11.11.23");
        annex.handle("sdsadsadsadas\\dsdsa\\sadas\\dsad.xxxdsadsadsawqeqwewq\\dsad\\aa\\中文.111")
                .forEach(System.out::println);
        annex.handle("sdsadsadsadashttp://www.fhgfguvj.com/sss/static/aaa.jssadsads<http://117.78.17.106:8121/h5/static/logo.png awqeqwewq\\dsad\\aa\\中文.111")
                .forEach(System.out::println);
        annex.handle("sdsadsadsadas\\dsdsa\\sadas\\dsad.xxxdsadshttp://192.168.22.142/sss/static/aaa.jswqeqwewq\\dsad\\aa\\中文.111")
                .forEach(System.out::println);
                annex.handle("http://sdsadsadsadas\\dsdsa\\sadas\\dsad.html<img src='W0202001321.jpg'>")
                .forEach(System.out::println);


        // List<HandleResult> listResult=annex.handle(FETCHED_FOLDER);
        // for (HandleResult handleResult : listResult) {
            
        // }

    }

   // public static List<Map<String,Object>> GetHandleResult(String ) 


    public class HandleResult{
        private String message;
        private int status;   //0:success    -1:fail
        private String path;   //filepath
        private int type;  //1: relative path   2: uri by domain  3: uri by ip

        public String getMessage() {
            return message;
        }

        public HandleResult setMessage(String message) {
            this.message = message;
            return this;
        }

        public String getPath() {
            return path;
        }

        public HandleResult setPath(String path) {
            this.path = path;
            return this;
        }

        public int getType() {
            return type;
        }

        public HandleResult setType(int type) {
            this.type = type;
            return this;
        }

        public int getStatus() {
            return status;
        }

        public HandleResult setStatus(int status) {
            this.status = status;
            return this;
        }

        @Override
        public String toString() {
            return "HandleResult{" +
                    "message='" + message + '\'' +
                    ", status=" + status +
                    ", path='" + path + '\'' +
                    ", type=" + type +
                    '}';
        }
    }

}
