package com.storlead.framework.common.util;

import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.FileItemStream;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

/**
 * @Description: 阿里云 oss 上传工具类(高依赖版)
 * @Date: 2019/5/10
 */
@Slf4j
public class OssBootUtil {

    private static Boolean loading;
    private static String endPoint;
    private static String accessKeyId;
    private static String accessKeySecret;
    private static String bucketName;

    public static void setLoading(Boolean loading) {
        OssBootUtil.loading = loading;
    }

    public static void setEndPoint(String endPoint) {
        OssBootUtil.endPoint = endPoint;
    }

    public static void setAccessKeyId(String accessKeyId) {
        OssBootUtil.accessKeyId = accessKeyId;
    }

    public static void setAccessKeySecret(String accessKeySecret) {
        OssBootUtil.accessKeySecret = accessKeySecret;
    }

    public static void setBucketName(String bucketName) {
        OssBootUtil.bucketName = bucketName;
    }

    /**
     * oss 工具客户端
     */
    private static OSSClient ossClient = null;
    private static String FILE_URL;

    /**
     * 上传文件至阿里云 OSS
     * 文件上传成功,返回文件完整访问路径
     * 文件上传失败,返回 null
     *
     * @param file    待上传文件
     * @param fileDir 文件保存目录
     * @return oss 中的相对文件路径
     */
    public static String upload(MultipartFile file, String fileDir) {
        initOSS(endPoint, accessKeyId, accessKeySecret);
        StringBuilder fileUrl = new StringBuilder();
        try {
            String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.'));
            String preffix = file.getOriginalFilename().substring(0,file.getOriginalFilename().lastIndexOf('.'));
            String fileName = preffix+DateUtils.getUploadFileName() + suffix;
            if (!fileDir.endsWith("/")) {
                fileDir = fileDir.concat("/");
            }
            fileUrl = fileUrl.append(fileDir + fileName);

            String fileUrl1 = "https://" + bucketName + "." + endPoint + "/" + fileUrl;
            //FILE_URL = staticDomain + "/" + fileUrl;
            PutObjectResult result = ossClient.putObject(bucketName, fileUrl.toString(), file.getInputStream());
            // 设置权限(公开读)
            ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
            if (result != null) {
                log.info("------OSS文件上传成功------" + fileUrl);
            }
            return fileUrl1;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }


    public static String upload(MultipartFile file, String fileDir,String newBucketName,String newEndPoint) {

        initOSS(endPoint, accessKeyId, accessKeySecret);
        StringBuilder fileUrl = new StringBuilder();
        try {
            String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.'));
            String preffix = file.getOriginalFilename().substring(0,file.getOriginalFilename().lastIndexOf('.'));
            String fileName = preffix+DateUtils.getUploadFileName() + suffix;
            if (!fileDir.endsWith("/")) {
                fileDir = fileDir.concat("/");
            }
            fileUrl = fileUrl.append(fileDir + fileName);
            String fileUrl1  = "https://" + newBucketName + "." + newEndPoint + "/" + fileUrl;
            //FILE_URL = staticDomain + "/" + fileUrl;
            PutObjectResult result = ossClient.putObject(newBucketName, fileUrl.toString(), file.getInputStream());
            // 设置权限(公开读)
            ossClient.setBucketAcl(newBucketName, CannedAccessControlList.PublicRead);
            if (result != null) {
                log.info("------OSS文件上传成功------" + fileUrl);
            }
            return fileUrl1;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 上传文件至阿里云 OSS
     * 文件上传成功,返回文件完整访问路径
     * 文件上传失败,返回 null
     *
     * @param file    待上传文件
     * @param fileDir 文件保存目录
     * @return oss 中的相对文件路径
     */
    public static String upload(FileItemStream file, String fileDir) {
        initOSS(endPoint, accessKeyId, accessKeySecret);
        StringBuilder fileUrl = new StringBuilder();
        try {
            String suffix = file.getName().substring(file.getName().lastIndexOf('.'));
            String fileName = UUID.randomUUID().toString().replace("-", "") + suffix;
            if (!fileDir.endsWith("/")) {
                fileDir = fileDir.concat("/");
            }
            fileUrl = fileUrl.append(fileDir + fileName);

            String fileUrl1  = "https://" + bucketName + "." + endPoint + "/" + fileUrl;
            //FILE_URL = staticDomain + "/" + fileUrl;
            PutObjectResult result = ossClient.putObject(bucketName, fileUrl.toString(), file.openStream());
            // 设置权限(公开读)
            ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
            if (result != null) {
                System.out.println("------OSS文件上传成功------" + fileUrl);
            }
            return fileUrl1;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据文件名下载文件 获取文件的流
     * 这里需要注意的就是 这里查找的oss文件目录是共有的目录 如果需要查找别的文件目录得话请勿使用该方法
     *
     * @param fileName 文件的名称 这里需要注意了这里的文件名是上传oss时候的文件名
     * @return null 表示文件不存在
     * @author timo
     * @date 2019/1/10 21:46
     */
    public static InputStream downloadObjFileToInputStream(String fileName) {
        return downloadObjFileToInputStream(bucketName, fileName);
    }

    /**
     * 根据文件名下载文件
     * 获取文件的流
     *
     * @param fileName   文件的名称 这里需要注意了这里的文件名是上传oss时候的文件名
     * @param bucketName oss文件所在的目录
     * @return null 表示文件不存在
     * @author timo
     * @date 2019/1/10 21:46
     */
    public static InputStream downloadObjFileToInputStream(String bucketName, String fileName) {
        try {
            OSSObject ossObject = new OSSClient(endPoint, accessKeyId, accessKeySecret).getObject(bucketName, fileName);
            if (ossObject == null) {
                throw new FileNotFoundException(fileName + " not in " + bucketName);
            }
            return ossObject.getObjectContent();
        } catch (Exception e) {
            e.getStackTrace();
            log.info("获取文件失败：" + e.toString() + e.getMessage(), e);
        }
        return null;
    }

    /**
     * 删除文件
     * @param url
     */
    public static void deleteUrl(String url) {
        String bucketUrl = "https://" + bucketName + "." + endPoint + "/";
        //String bucketUrl = staticDomain + "/";
        url = url.replace(bucketUrl,"");
        ossClient.deleteObject(bucketName, url);
    }

    /**
     * 删除文件
     * @param fileName
     */
    public static void delete(String fileName) {
        ossClient.deleteObject(bucketName, fileName);
    }

    /**
     * 初始化 oss 客户端
     *
     * @return
     */
    private static OSSClient initOSS(String endpoint, String accessKeyId, String accessKeySecret) {
        if (ossClient == null) {
            ossClient = new OSSClient(endpoint,
                    new DefaultCredentialProvider(accessKeyId, accessKeySecret),
                    new ClientConfiguration());
        }
        return ossClient;
    }

}
