package com.yihu.hos.core.datatype;


import com.yihu.hos.core.file.FileUtil;
import com.yihu.hos.core.log.Logger;
import com.yihu.hos.core.log.LoggerFactory;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;

public class ClassFileUtil {
    public static final String CLASS_FILE = ".class";
    public static final Logger logger = LoggerFactory.getLogger(ClassFileUtil.CLASS_FILE);
    public static final String JAVA_FILE = ".java";

    /**
     * 工具类不允许进行实例化
     */
    private ClassFileUtil() {

    }

    /**
     * 通过这个工具方法，可以进行class文件的创建
     *
     * @param url         本次进行系统创建的system业务系统存储class文件的根目录
     * @param packageName class文件的包信息
     * @param className   class文件的类名信息
     * @param path        class文件的路径
     */
    public static Boolean createClassfile(URL url, String packageName, String className, String path) {
        // 开始输出文件内容
        try {
            FileInputStream in = new FileInputStream(new File(path));
            File systemFlowFile = new File(url.getPath());
            if (!systemFlowFile.exists()) {
                systemFlowFile.mkdirs();
            }
            packageName = StringUtil.replaceStrAll(packageName, ".", "/");
            File packageFile = new File(url.getPath() + "/" + packageName);
            if (!packageFile.exists()) {
                packageFile.mkdirs();
            }
            String classPath = packageFile + "/" + className + ".class";
            File file = new File(classPath);
            if (file.isFile() && file.exists()) {
                file.delete();
            }
            file.createNewFile();

            FileOutputStream out = new FileOutputStream(classPath);
            int n = 0;// 每次读取的字节长度
            byte[] bb = new byte[1024];// 存储每次读取的内容
            while ((n = in.read(bb)) != -1) {
                out.write(bb, 0, n);// 将读取的内容，写入到输出流当中
            }
            out.close();
            in.close();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static Boolean updateClassfile(String classPath, String path) {
        // 开始输出文件内容
        try {
            FileInputStream in = new FileInputStream(new File(path));
            File file = new File(classPath);
            if (file.isFile() && file.exists()) {
                file.delete();
            } else {
                file.createNewFile();
            }
            FileOutputStream out = new FileOutputStream(classPath);
            int n = 0;// 每次读取的字节长度
            byte[] bb = new byte[1024];// 存储每次读取的内容
            while ((n = in.read(bb)) != -1) {
                out.write(bb, 0, n);// 将读取的内容，写入到输出流当中
            }
            out.close();
            in.close();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static Boolean deleteClassfile(String classPath) {
        // 开始输出文件内容
        try {
            boolean succ = false;
            File file = new File(classPath);
            if (file.isFile() && file.exists()) {
                succ = file.delete();
            }
            return succ;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 通过这个工具方法，可以进行class文件的创建
     *
     * @param url         本次进行系统创建的system业务系统存储class文件的根目录
     * @param packageName class文件的包信息
     * @param className   class文件的类名信息
     */
    public static FileOutputStream createClassfile(URL url, String packageName, String className) {
        // 开始输出文件内容
        try {
            String packagePath = StringUtil.replaceStrAll(packageName, ".", "/");
            File packageFile = new File(url.getPath() + "/" + packagePath);
            if (!packageFile.exists()) {
                packageFile.mkdirs();
            }
            String classPath = packageFile.getPath() + "/" + className + CLASS_FILE;
            File file = new File(classPath);
            if (file.isFile() && file.exists()) {
                file.delete();
            }
            file.createNewFile();

            FileOutputStream out = new FileOutputStream(classPath);
            return out;
        } catch (Exception e) {
            return null;
        }
    }

    public static FileOutputStream createFile(URL url, String packageName, String className, String fileType) {
        try {
            String packagePath = StringUtil.replaceStrAll(packageName, ".", "/");
            File packageFile = new File(url.getPath() + "/" + packagePath);
            if (!packageFile.exists()) {
                boolean mkdirs = packageFile.mkdirs();
                if (!mkdirs) {
                    return null;
                }
            }

            String classPath = packageFile.getPath() + "/" + className + fileType;
            File file = new File(classPath);
            if (file.isFile() && file.exists()) {
                boolean delete = file.delete();
                if (!delete) {
                    //Logger;
                    logger.warn("can't delete file, " + file.getAbsolutePath());
                }
            }
            boolean created = file.createNewFile();
            if (!created) {
                return null;
            }

            return new FileOutputStream(classPath);
        } catch (Exception e) {
            return null;
        }
    }

    public static String getFilePath(URL url, String packageName, String className, String fileType) {
        String packagePath = StringUtil.replaceStrAll(packageName, ".", "/");
        return url.getPath() + packagePath + "/" + className + fileType;
    }


    /**
     * 下载文件，返回下载后的文件地址
     * @param downUrl        http请求地址
     * @param url            本地保存根目录
     * @param packageName   包名
     * @param className     类名
     * @param fileType      文件类型
     * @return
     */
    public static String downFile(String downUrl,URL url, String packageName, String className, String fileType) {
        try {
            String packagePath = StringUtil.replaceStrAll(packageName, ".", "/");
            File packageFile = new File(url.getPath() + "/" + packagePath);
            if (!packageFile.exists()) {
                boolean mkdirs = packageFile.mkdirs();
                if (!mkdirs) {
                    return null;
                }
            }

            String classPath = packageFile.getPath() + "/" + className + fileType;
            byte[] bytes = down(downUrl);//文件内容
            boolean succ = FileUtil.writeFile(classPath,bytes,"UTF-8");//写入文件
            if (succ){
                return classPath;
            }else {
                return null;
            }
        } catch (Exception e) {
            return null;
        }
    }

    /**
     *  http接口下载文件
     * @param url  请求地址
     * @return
     */
    public static byte[] down( String url) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpget = new HttpGet(url);
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        try {
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(1000*60*5).setConnectTimeout(1000*60*5).build();//设置请求和传输超时时间
            httpget.setConfig(requestConfig);
            response = httpClient.execute(httpget);
            response.setHeader( "Content-Type", "application/octet-stream;charset=UTF-8");
            entity = response.getEntity();
            byte[] bytes= FileUtil.getBytesByStream(entity.getContent());
            return bytes;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                EntityUtils.consume(entity);
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return null;
    }

}
