package ink.wgink.module.file.utils;

import ink.wgink.exceptions.FileException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.exceptions.base.SystemException;
import ink.wgink.module.file.service.IFileService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * @ClassName: FileSaveUtil
 * @Description: 保存文件工具
 * @Author: wanggeng
 * @Date: 2022/8/3 21:12
 * @Version: 1.0
 */
public class FileUtil {

    private static final Logger LOG = LoggerFactory.getLogger(FileUtil.class);
    private static final char[] HEX_CODE = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    /**
     * 保存文件
     *
     * @param fileInputStream 文件流
     * @param fileName        文件名
     * @param filePath        保存路径
     * @return 文件大小
     */
    public static long save(InputStream fileInputStream, String fileName, String filePath) {
        File uploadFolder = new File(filePath);
        if (!uploadFolder.exists()) {
            uploadFolder.mkdirs();
        }
        FileOutputStream uploadFileOutputStream = null;
        long fileSize = 0;
        try {
            uploadFileOutputStream = new FileOutputStream(uploadFolder + File.separator + fileName);
            int readLength;
            for (byte[] buf = new byte[IFileService.INPUT_STREAM_SIZE]; (readLength = fileInputStream.read(buf)) > -1; ) {
                uploadFileOutputStream.write(buf, 0, readLength);
                fileSize += readLength;
            }
            uploadFileOutputStream.flush();
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            throw new FileException("文件上传失败");
        } finally {
            try {
                if (null != uploadFileOutputStream) {
                    uploadFileOutputStream.close();
                }
                if (null != fileInputStream) {
                    fileInputStream.close();
                }
            } catch (Exception e1) {
                LOG.error(e1.getMessage());
                throw new FileException("文件上传失败");
            }
        }
        return fileSize;
    }

    /**
     * 删除源文件
     *
     * @param sourceFilePath
     */
    public static boolean delete(String sourceFilePath) {
        File file = new File(sourceFilePath);
        if (file.exists()) {
            return file.delete();
        }
        return true;
    }

    /**
     * 获取文件的MD5
     *
     * @param file
     * @return
     */
    public static String getMD5(File file) {
        if (file == null) {
            throw new SearchException("文件不存在");
        }
        if (!file.exists()) {
            throw new SearchException("文件不存在");
        }
        String fileMd5;
        try (InputStream inputStream = Files.newInputStream(file.toPath())) {
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            int readLength;
            for (byte[] buf = new byte[IFileService.INPUT_STREAM_SIZE]; (readLength = inputStream.read(buf)) > -1; ) {
                messageDigest.update(buf, 0, readLength);
            }
            // 计算文件的MD5
            byte[] data = messageDigest.digest();
            StringBuilder fileMd5SB = new StringBuilder(data.length * 2);
            for (byte b : data) {
                fileMd5SB.append(HEX_CODE[(b >> 4) & 0xF]);
                fileMd5SB.append(HEX_CODE[(b & 0xF)]);
            }
            fileMd5 = fileMd5SB.toString();
        } catch (IOException | NoSuchAlgorithmException e) {
            throw new SystemException(e);
        }
        return fileMd5;
    }

}
