package com.tiesheng.core.service;

import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import com.tiesheng.core.config.web.TieshengWebConfigurer;
import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.pojos.FileUploadPath;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author hao
 */
@Service
public class FileUploadService {

    @Autowired(required = false)
    TieshengWebConfigurer tieshengWebConfigurer;


    ///////////////////////////////////////////////////////////////////////////
    // 方法
    ///////////////////////////////////////////////////////////////////////////

    /**
     * 保存文件
     *
     * @param file
     */
    public String saveMultipartFile(MultipartFile file) {
        try {

            if (tieshengWebConfigurer != null) {
                String fileType = FileTypeUtil.getType(file.getInputStream(), file.getOriginalFilename());
                tieshengWebConfigurer.uploadFileCheck(fileType);
            }

            FileUploadPath filePath = FileUploadPath.random();

            InputStream stream = file.getInputStream();
            FileUtil.writeFromStream(stream, filePath.getAbsolutePath());
            IoUtil.close(stream);

            return filePath.getHttpPath();
        } catch (Exception e) {
            throw new ApiException("文件流读取失败:" + e.getMessage());
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // 文件分包上传
    ///////////////////////////////////////////////////////////////////////////

    /**
     * 检查待上传文件是否存在
     *
     * @param fileExt
     */
    public void chunkStart(String fileExt) {
        if (tieshengWebConfigurer != null) {
            tieshengWebConfigurer.uploadFileCheck(fileExt);
        }
    }

    /**
     * 检查块文件
     *
     * @param fileMd5
     * @param chunk
     * @return
     */
    public boolean chunkCheck(String fileMd5, Integer chunk) {
        FileUploadPath folder = FileUploadPath.folder(fileMd5);
        File chunkFile = FileUtil.file(folder.getAbsolutePath(), chunk.toString());
        return chunkFile.exists();
    }

    /**
     * 块文件上传
     *
     * @param file
     * @param fileMd5
     * @param chunk
     */
    public void chunkUpload(MultipartFile file, String fileMd5, Integer chunk) {
        if (file == null) {
            throw new ApiException("请选择文件后上传");
        }

        try {
            // 块文件
            FileUploadPath folder = FileUploadPath.folder(fileMd5);
            File chunkfile = new File(folder.getAbsolutePath(), chunk.toString());
            InputStream stream = file.getInputStream();
            FileUtil.writeFromStream(stream, chunkfile);
            IoUtil.close(stream);
        } catch (Exception ignored) {
            throw new ApiException("块文件上传失败");
        }
    }

    /**
     * 合并块文件
     *
     * @param fileMd5
     * @param fileExt
     */
    public String chunkMerge(String fileMd5) {

        // 1，获取块文件的路径
        FileUploadPath folder = FileUploadPath.folder(fileMd5);

        // 2，生成保存文件路径
        FileUploadPath uploadPath = FileUploadPath.random();

        // 3，如果文件不存在
        if (FileUtil.exist(folder.getAbsolutePath())) {

            // 4，获取块文件，此列表是已经排好序的列表
            List<File> chunkFiles = getChunkFiles(new File(folder.getAbsolutePath()));

            // 5，合并文件
            File newFile = FileUtil.newFile(uploadPath.getAbsolutePath());
            for (File file : chunkFiles) {
                byte[] bytes = FileUtil.readBytes(file);
                FileUtil.writeBytes(bytes, newFile, 0, bytes.length, true);
            }

            // 6，删除块文件目录
            FileUtil.del(folder.getAbsolutePath());
        }

        return uploadPath.getHttpPath();

    }

    /**
     * 获取所有块文件
     *
     * @param chunkFileFolder
     * @return
     */
    private List<File> getChunkFiles(File chunkFileFolder) {

        //获取路径下的所有块文件
        File[] chunkFiles = chunkFileFolder.listFiles();
        if (chunkFiles == null) {
            return new ArrayList<>();
        }
        //将文件数组转成list，并排序
        List<File> chunkFileList = new ArrayList<>(Arrays.asList(chunkFiles));
        //排序
        chunkFileList.sort((o1, o2) -> {
            if (Integer.parseInt(o1.getName()) > Integer.parseInt(o2.getName())) {
                return 1;
            }
            return -1;
        });
        return chunkFileList;
    }

}
