package com.lunhan.xxx.common.util;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
 * 文件工具类
 * @author linliu
 * @date 2019-03-20
 */
public final class FileUtil {
    private FileUtil() {
        throw new IllegalStateException("Utility class");
    }

    static final String TITLE = "FileUtil";
    static final Integer EXCEL_SHEET_MAXROW = 65536;
    static final String STR_FAILD = "generate excel is faild!";
    static final String STR_UPLOADEXCEL = "list to excel and upload file service";
    static final String STR_DEFAULT_SHEETNAME = "Sheet1";

    /**
     * 根据文件contentType生成一个文件名
     * @param fileContentType contentType
     */
    public static String getNewFileNameByType(String fileContentType) {
        String timeStamp = Long.toString(System.currentTimeMillis());
        return timeStamp + FileUtil.getFileExtByType(fileContentType);
    }

    /**
     * 根据文件contentType生成一个文件名
     * @param fileContentType contentType
     */
    public static String getFileExtByType(String fileContentType) {
        String result = checkImage(fileContentType);
        if (StringUtil.isNotNullOrEmpty(result)) {
            return result;
        }

        result = checkRar(fileContentType);
        if (StringUtil.isNotNullOrEmpty(result)) {
            return result;
        }

        result = checkMedia(fileContentType);
        if (StringUtil.isNotNullOrEmpty(result)) {
            return result;
        }

        result = checkXml(fileContentType);
        if (StringUtil.isNotNullOrEmpty(result)) {
            return result;
        }

        result = checkOffice(fileContentType);
        if (StringUtil.isNotNullOrEmpty(result)) {
            return result;
        }
        return ".txt";
    }

    /**
     * 验证文件contentType是否是图片
     * @param fileContentType contentType
     */
    private static String checkImage(String fileContentType) {
        String result;
        switch (fileContentType) {
            case "image/jpeg":
            case "application/x-jpg":
                result = ".jpg";
                break;
            case "image/gif":
                result = ".gif";
                break;
            case "image/png":
                result = ".png";
                break;
            case "image/bmp":
                result = ".bmp";
                break;
            default:
                result = "";
                break;
        }
        return result;
    }

    /**
     * 验证文件contentType是否是压缩包
     * @param fileContentType contentType
     */
    private static String checkRar(String fileContentType) {
        String result;
        switch (fileContentType) {
            case "application/zip":
                result = ".zip";
                break;
            case "application/x-rar":
                result = ".rar";
                break;
            case "application/x-7z-compressed":
                result = ".7z";
                break;
            case "application/x-gzip":
                result = ".gz";
                break;
            default:
                result = "";
                break;
        }
        return result;
    }

    /**
     * 验证文件contentType是否是媒体文件
     * @param fileContentType contentType
     */
    private static String checkMedia(String fileContentType) {
        String result;
        switch (fileContentType) {
            case "video/mpeg":
                result = ".mp2";
                break;
            case "video/mp4":
                result = ".mp4";
                break;
            case "video/3gpp":
                result = ".3gp";
                break;
            case "video/x-flv":
                result = ".flv";
                break;

            case "audio/mpeg":
                result = ".mp3";
                break;
            case "audio/x-flac":
                result = ".flac";
                break;
            default:
                result = "";
                break;
        }
        return result;
    }

    /**
     * 验证文件contentType是否是xml
     * @param fileContentType contentType
     */
    private static String checkXml(String fileContentType) {
        String result;
        switch (fileContentType) {
            case "application/xml":
            case "text/html":
                result = ".xml";
                break;
            default:
                result = "";
                break;
        }
        return result;
    }

    /**
     * 验证文件contentType是否是office
     * @param fileContentType contentType
     */
    private static String checkOffice(String fileContentType) {
        String result;
        switch (fileContentType) {
            case "application/vnd.ms-excel":
                result = ".xls";
                break;
            case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
                result = ".xlsx";
                break;
            case "application/msword":
                result = ".doc";
                break;
            case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
                result = ".docx";
                break;
            case "application/vnd.ms-powerpoint":
                result = ".ppt";
                break;
            case "application/vnd.openxmlformats-officedocument.presentationml.presentation":
                result = ".pptx";
                break;
            default:
                result = "";
                break;
        }
        return result;
    }

    /**
     * 根据文件名识别文件 mediaType
     * @author linliu
     * @date 2019-06-26
     * @param fileName 文件名
     */
    public static String getMediaTypeByFileName(String fileName) {
        if (StringUtil.isNullOrEmpty(fileName)) {
            return "";
        }
        String[] arrayPath = StringUtil.split(fileName, "/");
        String realFileName = arrayPath[arrayPath.length - 1];
        String[] array = StringUtil.split(realFileName, "\\.");
        String fileSuffix = "." + array[array.length - 1];
        return getOfficeMediaTypeByFileName(fileSuffix);
    }

    /**
     * 根据文件拓展名识别 office文件
     * @param fileSuffix 拓展名
     */
    private static String getOfficeMediaTypeByFileName(String fileSuffix) {
        String result;
        switch (fileSuffix) {
            case ".xls":
                result = "application/vnd.ms-excel";
                break;
            case ".xlsx":
                result = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
                break;
            case ".doc":
                result = "application/msword";
                break;
            case ".docx":
                result = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
                break;
            case ".ppt":
                result = "application/vnd.ms-powerpoint";
                break;
            case ".pptx":
                result = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
                break;
            default:
                result = getImageMediaTypeByFileName(fileSuffix);
                break;
        }
        return result;
    }

    /**
     * 根据文件拓展名识别 图片文件
     * @param fileSuffix 拓展名
     */
    private static String getImageMediaTypeByFileName(String fileSuffix) {
        String result;
        switch (fileSuffix) {
            case ".jpeg":
                result = "image/jpeg";
                break;
            case ".jpg":
                result = "application/x-jpg";
                break;
            case ".gif":
                result = "image/gif";
                break;
            case ".png":
                result = "image/png";
                break;
            case ".bmp":
                result = "image/bmp";
                break;
            default:
                result = getRarMediaTypeByFileName(fileSuffix);
                break;
        }
        return result;
    }

    /**
     * 根据文件拓展名识别 压缩文件
     * @param fileSuffix 拓展名
     */
    private static String getRarMediaTypeByFileName(String fileSuffix) {
        String result;
        switch (fileSuffix) {
            case ".zip":
                result = "application/zip";
                break;
            case ".rar":
                result = "application/x-rar";
                break;
            case ".7z":
                result = "application/x-7z-compressed";
                break;
            case ".gz":
                result = "application/x-gzip";
                break;
            default:
                result = getOtherMediaTypeByFileName(fileSuffix);
                break;
        }
        return result;
    }

    /**
     * 根据文件拓展名识别 其他文件
     * @param fileSuffix 拓展名
     */
    private static String getOtherMediaTypeByFileName(String fileSuffix) {
        String result;
        switch (fileSuffix) {
            case ".pdf":
                result = "application/pdf";
                break;
            case ".txt":
                result = "text/plain";
                break;
            default:
                result = "";
                break;
        }
        return result;
    }

    /**
     * 读取本地文件内容
     * @param filePath 文件路径
     */
    public static String readFileContent(String filePath) {
        return readFileContent(filePath, null);
    }

    /**
     * 读取本地文件内容
     * @param filePath 文件路径
     * @param charset 编码格式
     */
    public static String readFileContent(String filePath, Charset charset) {
        if(null==charset) {
            charset = Charset.forName("utf-8");
        }
        File file = new File(filePath.replaceAll("\\\\", "/"));
        StringBuilder localStrBulider = new StringBuilder();
        if(file.isFile() && file.exists()) {
            String lineStr;
            try (InputStreamReader inputStreamReader=new InputStreamReader(new FileInputStream(file), charset)){
                BufferedReader bufferReader = new BufferedReader(inputStreamReader);
                while((lineStr = bufferReader.readLine()) != null) {
                    localStrBulider.append(lineStr);
                }
                bufferReader.close();
            } catch (IOException e) {
                //TODO log
            }
        } else {
            //TODO log
            return null;
        }
        return localStrBulider.toString();
    }

    /**
     * 读取本地文件内容
     * @param filePath 文件路径
     */
    public static byte[] readFile(String filePath) throws IOException {
        File f = new File(filePath);
        if (!f.exists()) {
            throw new FileNotFoundException(filePath);
        }

        ByteArrayOutputStream bos = new ByteArrayOutputStream((int) f.length());
        BufferedInputStream in = null;
        try {
            in = new BufferedInputStream(new FileInputStream(f));
            int bufSize = 1024;
            byte[] buffer = new byte[bufSize];
            int len;
            while (-1 != (len = in.read(buffer, 0, bufSize))) {
                bos.write(buffer, 0, len);
            }
            return bos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            bos.close();
        }
    }

    /**
     * 删除文件
     * @param path
     */
    public static void deleteFile(String path){
        File file=new File(path);
        if(file.exists()){
            file.delete();
        }
    }

    /**
     * 读取流内容
     * @param inputStream 流
     */
    public static String readFileContent(InputStream inputStream) {
        return FileUtil.readFileContent(inputStream, null);
    }

    /**
     * 读取流内容
     * @param inputStream 流
     * @param charset 编码格式
     */
    public static String readFileContent(InputStream inputStream, Charset charset) {
        if(null==charset) {
            charset = StandardCharsets.UTF_8;
        }
        StringBuilder localStrBulider = new StringBuilder();
        try (InputStreamReader inputStreamReader=new InputStreamReader(inputStream, charset)){
            BufferedReader bufferReader = new BufferedReader(inputStreamReader);
            String lineStr;
            while((lineStr = bufferReader.readLine()) != null) {
                localStrBulider.append(lineStr);
            }
            bufferReader.close();
        } catch (IOException e) {
            //TODO log
        }
        return localStrBulider.toString();
    }
}