package com.qmth.themis.business.util;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import com.qmth.themis.business.constant.SystemConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @Description: oss工具
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/4/4
 */
@Component
public class OssUtil {
    private final static Logger log = LoggerFactory.getLogger(OssUtil.class);

    /**
     * oss上传文件
     *
     * @param map
     * @param dirName
     * @param inputStream
     */
    public void ossUpload(Map<String, Object> map, String dirName, InputStream inputStream) {
        log.info("ossUpload is come in");
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        String endpoint = String.valueOf(map.get(SystemConstant.END_POINT));
        // 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
        String accessKeyId = String.valueOf(map.get(SystemConstant.ACCESS_KEY_ID));
        String accessKeySecret = String.valueOf(map.get(SystemConstant.ACCESS_KEY_SECRET));
        String bucketName = String.valueOf(map.get(SystemConstant.BUCKET));
        // <yourObjectName>上传文件到OSS时需要指定包含文件后缀在内的完整路径，例如abc/efg/123.jpg。
        String objectName = dirName;
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // 上传内容到指定的存储空间（bucketName）并保存为指定的文件名称（objectName）。
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
        PutObjectResult por = ossClient.putObject(putObjectRequest);
        log.info("objectName:{},requestid:{}", objectName, por.getRequestId());
    }

    /**
     * oss上传文件
     *
     * @param map
     * @param dirName
     * @param content
     */
    public void ossUpload(Map<String, Object> map, String dirName, String content) {
        log.info("ossUpload is come in");
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        String endpoint = String.valueOf(map.get(SystemConstant.END_POINT));
        // 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
        String accessKeyId = String.valueOf(map.get(SystemConstant.ACCESS_KEY_ID));
        String accessKeySecret = String.valueOf(map.get(SystemConstant.ACCESS_KEY_SECRET));
        String bucketName = String.valueOf(map.get(SystemConstant.BUCKET));
        // <yourObjectName>上传文件到OSS时需要指定包含文件后缀在内的完整路径，例如abc/efg/123.jpg。
        String objectName = dirName;
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // 上传内容到指定的存储空间（bucketName）并保存为指定的文件名称（objectName）。
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));
        PutObjectResult por = ossClient.putObject(putObjectRequest);
        log.info("objectName:{},requestid:{}", objectName, por.getRequestId());
    }

    /**
     * oss copy
     *
     * @param map
     * @param dirName
     * @param dirNewName
     */
    public void ossCopy(Map<String, Object> map, String dirName, String dirNewName) {
        log.info("ossCopy is come in");
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        String endpoint = String.valueOf(map.get(SystemConstant.END_POINT));
        // 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
        String accessKeyId = String.valueOf(map.get(SystemConstant.ACCESS_KEY_ID));
        String accessKeySecret = String.valueOf(map.get(SystemConstant.ACCESS_KEY_SECRET));
        String sourceBucketName = String.valueOf(map.get(SystemConstant.BUCKET));
        String sourceObjectName = dirName;
        String destinationBucketName = String.valueOf(map.get(SystemConstant.BUCKET));
        String destinationObjectName = dirNewName;
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // 拷贝文件。
        CopyObjectResult result = ossClient.copyObject(sourceBucketName, sourceObjectName, destinationBucketName, destinationObjectName);
        log.info("ETag:{},LastModified:{}", result.getETag(), result.getLastModified());
        // 关闭OSSClient。
        ossClient.shutdown();
    }

    /**
     * 从oss上下载文件到本地
     *
     * @param map
     * @param dirName
     * @param localPath
     * @throws IOException
     */
    public File ossDownload(Map<String, Object> map, String dirName, String localPath) throws IOException {
        log.info("ossDownload is come in");
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        String endpoint = String.valueOf(map.get(SystemConstant.END_POINT));
        // 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
        String accessKeyId = String.valueOf(map.get(SystemConstant.ACCESS_KEY_ID));
        String accessKeySecret = String.valueOf(map.get(SystemConstant.ACCESS_KEY_SECRET));
        String bucketName = String.valueOf(map.get(SystemConstant.BUCKET));
        // <yourObjectName>从OSS下载文件时需要指定包含文件后缀在内的完整路径，例如abc/efg/123.jpg。
        String objectName = dirName;
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖，不存在则新建。
        File localFile = new File(localPath);
        if (!localFile.getParentFile().exists()) {
            localFile.getParentFile().mkdirs();
        }
        ossClient.getObject(new GetObjectRequest(bucketName, objectName), localFile);
        // 关闭OSSClient。
        ossClient.shutdown();
        return localFile;
    }

    /**
     * oss删除文件
     *
     * @param map
     * @param dirName
     */
    public void ossDelete(Map<String, Object> map, String dirName) {
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        String endpoint = String.valueOf(map.get(SystemConstant.END_POINT));
        // 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
        String accessKeyId = String.valueOf(map.get(SystemConstant.ACCESS_KEY_ID));
        String accessKeySecret = String.valueOf(map.get(SystemConstant.ACCESS_KEY_SECRET));
        String bucketName = String.valueOf(map.get(SystemConstant.BUCKET));
        String objectName = dirName;

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // 删除文件。如需删除文件夹，请将ObjectName设置为对应的文件夹名称。如果文件夹非空，则需要将文件夹下的所有object删除后才能删除该文件夹。
        ossClient.deleteObject(bucketName, objectName);
        // 关闭OSSClient。
        ossClient.shutdown();
    }

    /**
     * oss批量删除文件
     *
     * @param map
     * @param paths
     */
    public void ossBatchDelete(Map<String, Object> map, List<String> paths) {
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        String endpoint = String.valueOf(map.get(SystemConstant.END_POINT));
        // 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
        String accessKeyId = String.valueOf(map.get(SystemConstant.ACCESS_KEY_ID));
        String accessKeySecret = String.valueOf(map.get(SystemConstant.ACCESS_KEY_SECRET));
        String bucketName = String.valueOf(map.get(SystemConstant.BUCKET));

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        // 删除文件。key等同于ObjectName，表示删除OSS文件时需要指定包含文件后缀在内的完整路径，例如abc/efg/123.jpg。
        DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(paths));
        List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
        // 关闭OSSClient。
        ossClient.shutdown();
    }
    
    /** 获取私有bucket文件访问url，一分钟有效
     * @param map
     * @param objectPath
     * @param inputStream
     * @return
     */
    public static String getUrlForPrivateBucket(Map<String, Object> map, String objectPath) {
        String endpoint = String.valueOf(map.get(SystemConstant.END_POINT));
        String accessKeyId = String.valueOf(map.get(SystemConstant.ACCESS_KEY_ID));
        String accessKeySecret = String.valueOf(map.get(SystemConstant.ACCESS_KEY_SECRET));
        String bucketName = String.valueOf(map.get(SystemConstant.BUCKET));
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        Date expiration = new Date(System.currentTimeMillis() + 60 * 1000);
        GeneratePresignedUrlRequest generatePresignedUrlRequest ;
        generatePresignedUrlRequest =new GeneratePresignedUrlRequest(bucketName, objectPath);
        generatePresignedUrlRequest.setExpiration(expiration);
        URL url = ossClient.generatePresignedUrl(generatePresignedUrlRequest);
        return url.toString();
    }
    
    public static void ossUpload(Map<String, Object> map, String path, File file) {
        String endpoint = String.valueOf(map.get(SystemConstant.END_POINT));
        String accessKeyId = String.valueOf(map.get(SystemConstant.ACCESS_KEY_ID));
        String accessKeySecret = String.valueOf(map.get(SystemConstant.ACCESS_KEY_SECRET));
        String bucketName = String.valueOf(map.get(SystemConstant.BUCKET));
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, path, file);
        ossClient.putObject(putObjectRequest);
    }
    
    public static void ossUploadStream(Map<String, Object> map, String path, InputStream inputStream) {
        String endpoint = String.valueOf(map.get(SystemConstant.END_POINT));
        String accessKeyId = String.valueOf(map.get(SystemConstant.ACCESS_KEY_ID));
        String accessKeySecret = String.valueOf(map.get(SystemConstant.ACCESS_KEY_SECRET));
        String bucketName = String.valueOf(map.get(SystemConstant.BUCKET));
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, path, inputStream);
        ossClient.putObject(putObjectRequest);
    }
}
