package com.reyun.saas.common.framework.component;

import com.amazonaws.HttpMethod;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import com.reyun.saas.common.util.IOUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;

/**
 * @desc
 * @date 官方文档https://docs.amazonaws.cn/AmazonS3/latest/userguide/UsingObjects.html
 */
@Component
@Slf4j
public class AwsS3Component {
    @Value("${S3.accessKeyId}")
    private String accessKeyId;
    @Value("${S3.accessKeySecret}")
    private String accessKeySecret;
    @Value("${S3.bucketName}")
    private String bucketName;
    @Value("${S3.region}")
    private String regionName;

    private AmazonS3 s3;

    public String getBucketName() {
        return bucketName;
    }

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

    @PostConstruct
    public void init() {
        AWSCredentials awsCredentials = new BasicAWSCredentials(accessKeyId, accessKeySecret);
        AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(awsCredentials));
        //设置S3的地区
        builder.setRegion(regionName);
        s3 = builder.build();
    }

    public PutObjectResult upload(String fileName, InputStream inputStream){
        try {
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentType("plain/text");
            objectMetadata.setContentLength(Long.valueOf(inputStream.available()));
            PutObjectResult putObjectRequest = s3.putObject(new PutObjectRequest(bucketName, fileName, inputStream, objectMetadata));
            return putObjectRequest ;
        }catch (Exception e){
            log.error("S3:upload异常",e);
        }
        return null;
    }

    public URL generatePresignedUrl(String objectName, long expireMsFromCurrent) {
        try {
            java.util.Date expiration = new java.util.Date();
            long expTimeMillis = expiration.getTime();
            expTimeMillis += expireMsFromCurrent;
            expiration.setTime(expTimeMillis);
            GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName,
                    objectName).withMethod(HttpMethod.GET).withExpiration(expiration);
            return s3.generatePresignedUrl(generatePresignedUrlRequest);
        }catch (Exception e){
            log.error("S3:upload异常",e);
        }
        return null;
    }

    public void deleteS3Object(String s3key) {
        s3.deleteObject(bucketName, s3key);
    }

    public boolean doesObjectExist(String objectName) {
        if(StringUtils.isEmpty(objectName)){
            return false;
        }
        return s3.doesObjectExist(bucketName, objectName);
    }

    /**
     * 获取文件大小
     */
    public long length(String bucket, String s3key)
    {
        long len = 0;
        final S3Object s3Object = s3.getObject(bucket, s3key);
        try {
            if (s3Object != null) {
                len = s3Object.getObjectMetadata().getContentLength();
            }
        }
        finally {
            try {
                if (s3Object != null) {
                    s3Object.close();
                }
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
        return len;
    }

    /**
     * 上传文件
     * @param bucket 桶名
     * @param s3key key
     * @param in 输入流
     * @param contentType 文件类型
     * @param contentLength 文件大小
     * @param expireTime 过期时间 毫秒
     */
    public void uploadStreamToS3(String bucket, String s3key, InputStream in, String contentType, long contentLength,
                                 long expireTime) {
        if(StringUtils.isEmpty(contentType)){
            contentType = "application/x-download; charset=UTF-8";
        }
        ObjectMetadata md = new ObjectMetadata();
        if (contentType != null) {
            md.setContentType(contentType);
        }
        md.setContentLength(contentLength);
        if (expireTime > 0L) {
            Date expire = new Date(System.currentTimeMillis() + expireTime);
            md.setExpirationTime(expire);
        }
        s3.putObject(bucket, s3key, in, md);
    }

    /**
     * 获取s3文件的流
     */
    public InputStream downloadStreamFromS3(String bucket, String s3key) {
        final S3Object s3Object = s3.getObject(bucket, s3key);
        return s3Object.getObjectContent();
    }

    /**
     * 获取s3中的文件(byte数组)
     */
    public byte[] downloadBytesFromS3(String bucket, String s3key)
            throws IOException
    {
        InputStream is = null;
        ByteArrayOutputStream bos = null;
        try {
            is = s3.getObject(bucket, s3key).getObjectContent();
            bos = new ByteArrayOutputStream();
            IOUtil.copy(is, bos);
            return bos.toByteArray();
        }
        finally {
            if (bos != null) {
                IOUtil.close(bos);
            }
            if (is != null) {
                IOUtil.close(is);
            }
        }
    }
}
