package com.app.framework.core.utils.file;

import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import com.app.framework.core.exception.ValidException;
import com.app.framework.core.utils.request.RequestUtil;
import lombok.Data;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * 上传文件工具类
 */
public class UploadUtil {
    private static final Logger log = LoggerFactory.getLogger(UploadUtil.class);

    private final static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd");

    /**
     * 上传路径
     */
    private static String uploadPath;

    /**
     * 访问地址的baseUrl
     */
    private static String baseUrl;

    /**
     * 根目录名称
     * 默认uploadfiles
     */
    private static String rootDirName;

    public static void init(String uploadPath, String baseUrl) {
        if (UploadUtil.uploadPath == null || !UploadUtil.uploadPath.equals(uploadPath)) {
            UploadUtil.uploadPath = uploadPath;
        }
        if (UploadUtil.baseUrl == null || !UploadUtil.baseUrl.equals(baseUrl)) {
            UploadUtil.baseUrl = baseUrl;
        }
    }

    public static String getBaseUrl(HttpServletRequest request) {
        if (StringUtils.isBlank(baseUrl)) {
            baseUrl = RequestUtil.getBasePath(request);
        }
        return baseUrl;
    }

    public static String getRootDirName() {
        if (StringUtils.isBlank(rootDirName)) {
            if (StringUtils.isBlank(uploadPath) || "/".equals(uploadPath)) {//上传到项目根目录
                rootDirName = "/uploadfiles";
            } else {
                rootDirName = uploadPath.substring(uploadPath.lastIndexOf("/"));
            }
        }
        return rootDirName;
    }

    public static String getUploadPath(String savePath) {
        if (StringUtils.isBlank(savePath)) {
            savePath = DATE_FORMAT.format(new Date());
        }
        if (!savePath.startsWith("/")) {
            savePath = new StringBuilder().append("/").append(savePath).toString();
        }
        StringBuilder builder = new StringBuilder();
        if (StringUtils.isBlank(uploadPath)) {
            builder.append(getRootDirName()).append(savePath);
        } else {
            builder.append(uploadPath).append(savePath);
        }
        return builder.toString();
    }

    public static String getBaseUrl(HttpServletRequest request, String savePath) {
        if (StringUtils.isBlank(savePath)) {
            savePath = DATE_FORMAT.format(new Date());
        }
        if (!savePath.startsWith("/")) {
            savePath = new StringBuilder().append("/").append(savePath).toString();
        }
        String baseUrl = getBaseUrl(request);
        StringBuilder url = new StringBuilder(baseUrl);
        if (!baseUrl.endsWith(getRootDirName())) {
            url.append(getRootDirName());
        }
        url.append(savePath);
        return url.toString();
    }

    public static String upload(MultipartHttpServletRequest multipartRequest, UploadConfig uploadConfig) throws Exception {
        init(uploadConfig.getUploadPath(), uploadConfig.getBaseUrl());

        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        MultipartFile multipartFile = fileMap.values().iterator().next();
        if (multipartFile == null) {
            throw new ValidException("请选择文件");
        }
        long size = multipartFile.getSize();
		if(uploadConfig.getFileSingleSizeLimit() > 0 && size > uploadConfig.getFileSingleSizeLimit()){//单个文件大小超过限制
			throw new ValidException("文件大小超过限制");
		}
        String contentType = multipartFile.getContentType();
        String ext = FileUtil.getSuffix(multipartFile.getOriginalFilename());

        log.info("文件长度: " + size);
        log.info("文件类型: " + contentType);
        log.info("文件扩展名: " + ext);
        log.info("文件原名: " + multipartFile.getOriginalFilename());

        String fileName = new StringBuilder().append(System.nanoTime()).append(RandomUtil.randomString(6)).append(".").append(ext).toString();
        File file = new File(getUploadPath(null));
        if (!file.exists()) {
            file.mkdirs();
            log.info("创建文件路径: " + file.getAbsolutePath());
        }
        File createFile = new File(getUploadPath(null), fileName);
        //处理压缩
        if (uploadConfig != null && uploadConfig.isCompress() && size > uploadConfig.getCompressSize()) {
            //判断是否压缩gif图片
            if (ext.equalsIgnoreCase("gif") && !uploadConfig.isCompressGif()) {//不压缩gif图片
                FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), createFile);
            } else {
                BufferedImage oldImage = ImageIO.read(multipartFile.getInputStream());
                if (uploadConfig.getCompressScale() > 0) {
                    Image scale = ImgUtil.scale(oldImage, uploadConfig.getCompressScale());
                    ImgUtil.write(scale, createFile);
                } else if (uploadConfig.getCompressWidth() > 0 && uploadConfig.getCompressHeight() > 0) {
                    Image scale = ImgUtil.scale(oldImage, uploadConfig.getCompressWidth(), uploadConfig.getCompressHeight());
                    ImgUtil.write(scale, createFile);
                } else {
                    Image scale = ImgUtil.scale(oldImage, 1);
                    ImgUtil.write(scale, createFile);
                }
            }
        } else {
            FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), createFile);
        }
        log.info("创建成功: " + createFile.getAbsolutePath());

        return getBaseUrl(multipartRequest, null) + "/" + fileName;
    }

    @Data
    public static class UploadConfig implements Serializable {
        private static final long serialVersionUID = 1L;

        /**
         * 上传路径
         */
        private String uploadPath;

        /**
         * 访问地址的baseUrl
         */
        private String baseUrl;

        /**
         * 单个文件大小限制
         */
        private long fileSingleSizeLimit;

        /**
         * 是否压缩
         */
        private boolean compress;
        /**
         * 压缩后的宽
         */
        private int compressWidth;
        /**
         * 压缩后的高
         */
        private int compressHeight;
        /**
         * 压缩比例
         */
        private float compressScale;
        /**
         * 如果图片大小小于此值，不再压缩，单位字节
         */
        private long compressSize;
        /**
         * 是否压缩gif图片，默认false
         */
        private boolean compressGif;
    }

}