package xyz.wbsite.frame.utils;

import org.springframework.boot.system.ApplicationHome;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Pattern;

/**
 * Resource资源文件工具
 *
 * @author wangbing
 * @version 0.0.1
 * @since 2017-01-01
 */
public class ResourceUtil extends ResourceUtils {

    /**
     * 获取当前运行主目录
     * 当开发时获取:E:\...\classes
     * 当JAR包时: E:\...\***.jar
     *
     * @return jar路径
     */
    public static File getApplicationHome() {
        ApplicationHome home = new ApplicationHome(ResourceUtil.class);
        return home.getSource();
    }

    /**
     * 列出指定目录下文件名
     *
     * @param resourcePath 目录
     * @return 文件名集合
     */
    public static List<String> listFileName(String resourcePath) {
        if (!resourcePath.endsWith("/")) {
            resourcePath = resourcePath + "/";
        }
        List<String> result = new ArrayList<>();
        List<URL> urls = ResourceUtil.listURL(resourcePath);
        for (URL url : urls) {
            File file1 = new File(url.getFile());
            if (file1.isFile()) {
                result.add(file1.getName());
            } else if (!file1.isDirectory() && !url.getFile().endsWith("/")) {
                result.add(file1.getName());
            }
        }
        return result;
    }

    /**
     * @param resourceLocation 资源路径
     * @return URL
     * @throws FileNotFoundException 文件未找到异常
     */
    public static URL getURL(String resourceLocation) throws FileNotFoundException {
        if (!resourceLocation.startsWith("classpath:")) {
            resourceLocation = "classpath:" + resourceLocation;
        }
        return ResourceUtils.getURL(resourceLocation);
    }

    /**
     * 获取资源目录下所有文件名 如: /modules/dir/
     *
     * @param resourcePath 路径
     * @return
     */
    public static List<URL> listURL(String resourcePath) {
        if (!resourcePath.startsWith("/")) {
            resourcePath = "/" + resourcePath;
        }
        if (!resourcePath.endsWith("/")) {
            resourcePath = resourcePath + "/";
        }
        List<URL> result = new ArrayList<>();
        File applicationHome = getApplicationHome();
        if (applicationHome.getName().endsWith(".jar")) {
            try {
                Pattern pattern = Pattern.compile("BOOT-INF/classes" + resourcePath + "[^/]+/?$");
                JarFile jarFile = new JarFile(applicationHome);
                Enumeration<JarEntry> entries = jarFile.entries();
                while (entries.hasMoreElements()) {
                    JarEntry jarEntry = entries.nextElement();
                    String name = jarEntry.getName();
                    if (pattern.matcher(name).find()) {
                        result.add(getURL(name));
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            try {
                ClassPathResource cpr = new ClassPathResource(resourcePath);
                File in = cpr.getFile();
                for (File file : in.listFiles()) {
                    result.add(FileUtil.getURL(file.getAbsolutePath()));
                }
                return result;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 获取资源输入流
     *
     * @return 资源路径
     */
    public static InputStream getInput(String resourceLocation) {
        try {
            ClassPathResource classPathResource = new ClassPathResource(resourceLocation);
            return classPathResource.getInputStream();
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * 获取资源的的字节数组
     *
     * @return 字节数组
     */
    public static byte[] getBytes(String resourceLocation) {
        InputStream is = null;
        byte[] result = null;
        try {
            is = getInput(resourceLocation);
            result = new byte[is.available()];
            is.read(result);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 复制类文件下的资源文件
     *
     * @param resourceLocation 资源路径
     * @param file             输出文件
     * @return 成功或失败情况
     */
    public static boolean copyToFile(String resourceLocation, File file) {
        InputStream resourceInput = getInput(resourceLocation);
        FileOutputStream fileOutputStream = null;
        try {
            if (!file.exists()) {
                throw new RuntimeException(file.getAbsolutePath() + " not exists!");
            }
            fileOutputStream = FileUtil.openOutputStream(file);
            FileUtil.copy(resourceInput, fileOutputStream);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (fileOutputStream != null) fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }
}