package com.ruoyi.common.utils.ossutil;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.ruoyi.common.exception.base.BaseException;
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;


@Component
public class OssUtil {

    /*private OssUtil() {
        throw new IllegalStateException("unit class");
    }*/

    private final static Logger logger = LoggerFactory.getLogger(OssUtil.class);

    @Value("${aliyun.oss.endpoint}")
    private String endpoint;

    @Value("${aliyun.oss.bucketName}")
    private String bucketName;

    @Value("${aliyun.oss.accessKeyId}")
    private String accessKeyId;

    @Value("${aliyun.oss.accessKeySecret}")
    private String accessKeySecret;

    @Value("${aliyun.oss.prefix}")
    private String prefix;


    /**
     * 多文件上传
     *
     * @param files 文件列表
     * @return 返回urls
     */
    public List<String> uploadFiles(MultipartFile[] files, String local, boolean usePrefix) {
        List<String> urls = Arrays.asList(new String[files.length]);
        AtomicReference<Integer> count = new AtomicReference<>(0);
        long totalSize = 0L;
        for (int i = 0, len = files.length; i < len; i++) {
            totalSize += files[i].getSize();
            threadUpload(i, count, urls, files[i], local, usePrefix);
        }

        while (true) {
            if (count.get() == files.length || totalSize <= 0) {
                break;
            }
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                logger.info("==================上传文件时线程睡眠异常：" + e.getMessage());
            }
            totalSize -= 512; //按照 50kb/s 的标准计算超时时间
        }
        return urls;
    }

    /**
     * 线程上传文件
     *
     * @param i
     * @param urls
     * @param file
     */
    public void threadUpload(int i, AtomicReference<Integer> count, List<String> urls, MultipartFile file, String local, boolean usePrefix) {
        new Thread(() -> {
            urls.set(i, ossUpload(file, usePrefix, local));
            count.updateAndGet(v -> v + 1);
        }).start();
    }

    /**
     * 上传文件
     *
     * @param file 文件
     * @return
     * @throws IOException
     */
    public String ossUpload(MultipartFile file, boolean usePrefix, String local) {
        if (file == null) {
            return null;
        }
        /*ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            Thumbnails.of(file.getInputStream())
                    .scale(.6)
                    .outputQuality(.5)
                    .toOutputStream(out);

        } catch (IOException e) {
            e.printStackTrace();
        }*/
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // 上传文件流。
//        InputStream inputStream = null;
//        try {
        //inputStream = file.getInputStream();
//        byte[] bytes = out.toByteArray();
//        logger.info("===========zip length:{}", bytes.length);
//            if(bytes.length > 0){
//        InputStream inputStream = new ByteArrayInputStream(bytes);
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
            throw new BaseException("IO异常");
        }
//            }

        /*} catch (IOException e) {
            logger.info("======================获得文件流异常：" + e.getMessage());
        }*/
        String objName = file.getOriginalFilename();
        if(objName == null){
            objName = Math.random() + "";
        }
        LocalDateTime dateTime = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String dateFolder = (local.length() > 0 ? (local + "/") : "") + getFileType(objName) + "/" + formatter.format(dateTime).replaceAll("-", "/");
        try {
            objName = URLEncoder.encode(objName, "utf8");
            objName = objName.replaceAll("%", "");
            objName = objName.replaceAll("\\+", "-");
        } catch (UnsupportedEncodingException e) {
            logger.error("=====================文件名编码异常：" + e.getMessage());
        }
        String random = System.currentTimeMillis() + "_";
        ossClient.putObject(bucketName, dateFolder + "/" + random + objName, inputStream);
        // 关闭OSSClient。
        ossClient.shutdown();
        return (usePrefix ? prefix : "") + "/" + dateFolder + "/" + random + objName;
    }

    /**
     * 获取文件类型
     *
     * @param chars
     * @return
     */
    public static OssFileType getFileType(String chars) {
        OssFileType fileType;
        switch (chars.substring(chars.lastIndexOf(".") + 1).toLowerCase()) {
            case "png":
            case "jpg":
            case "jpeg":
            case "gif":
                fileType = OssFileType.image;
                break;
            case "mp4":
            case "avi":
                fileType = OssFileType.video;
                break;
            case "mp3":
            case "m4a":
            case "wav":
                fileType = OssFileType.audio;
                break;
            case "xls":
            case "xlsx":
            case "xlxs":
            case "cvs":
                fileType = OssFileType.excel;
                break;
            case "doc":
            case "docx":
                fileType = OssFileType.word;
                break;
            case "pdf":
                fileType = OssFileType.pdf;
                break;
            case "ppt":
                fileType = OssFileType.ppt;
                break;
            default:
                fileType = OssFileType.other;
        }
        return fileType;
    }

}