package com.emergency.avenue.admin.config;


import io.minio.*;
import io.minio.errors.*;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * @Description: Minio操作工具类
 * @Author:  x
 * @CreateTime: 2023/2/3 15:36
 * @LastEditors: x
 * @LastEditTime: 2023/2/3 15:36
 */

public class MinioTemplate implements Serializable {

	/**
	 * 判断bucket是否存在，不存在则创建
	 *
	 * @param minioClient
	 * @param bucketName
	 * @throws Exception
	 */
	public static final void bucketExists(MinioClient minioClient, String bucketName) throws Exception {
		boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
		if (!found) {
			// Make a new bucket called 'bucketName'.
			minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
		}
	}

	/**
	 * 上传对象
	 *
	 * @param minioClient 客户端操作对象
	 * @param bucketName  桶名称
	 * @param objectName  文件名
	 * @param filePath    文件路径
	 * @return
	 * @throws Exception
	 * @throws ServerException
	 * @throws InsufficientDataException
	 * @throws ErrorResponseException
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeyException
	 * @throws InvalidResponseException
	 * @throws XmlParserException
	 * @throws InternalException
	 */
	public static final ObjectWriteResponse uploadObject(MinioClient minioClient, String bucketName, String objectName, String filePath) throws Exception {
		bucketExists(minioClient, bucketName);
		return minioClient.uploadObject(UploadObjectArgs.builder().bucket(bucketName).object(objectName).filename(filePath).build());
	}
	public static final ObjectWriteResponse uploadObject(MinioClient minioClient, String bucketName,String fileName,MultipartFile file) throws Exception{
		bucketExists(minioClient, bucketName);
		PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(fileName)
				.stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
		//文件名称相同会覆盖
		return minioClient.putObject(objectArgs);
	}

	public static void removeObject(MinioClient minioClient, String bucketName, String fileName) throws Exception{
		RemoveObjectArgs objectArgs = RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build();
		minioClient.removeObject(  objectArgs );
	}

	/**
	 * @param minioClient 客户端操作对象
	 * @param bucketName  桶名称
	 * @param objectName  文件名
	 * @param contentType 文件类型
	 * @param filePath    文件路径
	 * @return
	 * @throws Exception
	 */
	public static final ObjectWriteResponse uploadObject(MinioClient minioClient, String bucketName, String objectName, String contentType, String filePath) throws Exception {
		bucketExists(minioClient, bucketName);
		return minioClient.uploadObject(UploadObjectArgs.builder().bucket(bucketName).object(objectName).filename(filePath).contentType(contentType).build());
	}

	/**
	 * 上传MultipartFile接收的文件
	 *
	 * @param minioClient minio客户端对象
	 * @param bucketName  桶名
	 * @param objectName  文件名，如 aa.png
	 * @param file        MultipartFile对象
	 * @return
	 * @throws Exception
	 */
	public static final ObjectWriteResponse uploadObjectByMultipartFile(MinioClient minioClient, String bucketName, String objectName, MultipartFile file) throws Exception {
		bucketExists(minioClient, bucketName);
       /* InputStream inputStream = file.getInputStream();
        return minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).contentType(file.getContentType()).stream(inputStream, inputStream.available(), -1).build());*/
		return minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).contentType(file.getContentType()).stream(file.getInputStream(), file.getSize(), -1).build());
	}

	/**
	 * 对上传的文件名进行处理:最终格式为：文件名_当前系统时间的毫米数.后缀类型
	 *
	 * @param fileName
	 * @return
	 */
	public static final String replaceFileName(String fileName) {
		String newFileName = null;
		if (StringUtils.hasLength(fileName)) {
			String fileNamePre = fileName.substring(0, fileName.lastIndexOf("."));
			String fileNameSuffix = fileName.substring(fileName.lastIndexOf("."));
			newFileName = fileNamePre + "_" + System.currentTimeMillis() + fileNameSuffix;
		}
		return newFileName;
	}

	/**
	 * 对上传的文件名进行处理：文件名 指定的分隔符 当前系统时间的毫秒数.后缀类型
	 *
	 * @param fileName
	 * @param splitStr
	 * @return
	 */
	public static final String replaceFileName(String fileName, String splitStr) {
		String newFileName = null;
		if (StringUtils.hasLength(fileName)) {
			String fileNamePre = fileName.substring(0, fileName.lastIndexOf("."));
			String fileNameSuffix = fileName.substring(fileName.lastIndexOf("."));
			newFileName = fileNamePre + (splitStr == null ? "_" : splitStr) + System.currentTimeMillis() + fileNameSuffix;
		}
		return newFileName;
	}

	/**
	 * description: 从minio下载对象到本地_通过流的方式输出
	 *
	 * @param minioClient    MinioClient客户端对象
	 * @param bucketName     桶名
	 * @param objectName     对象全名，如： yuantest/test/3639dfb5ceeb4ae290a3de68c8321cac.docx
	 * @param fileOutputPath fileOutputPath 文件输出位置： 如：D:\aa\files\Java开发手册(黄山版).pdf
	 * @throws Exception
	 */
	public static void downloadToLocalByStream(MinioClient minioClient, String bucketName, String objectName, String fileOutputPath) throws Exception {
		InputStream in = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
		FileOutputStream outputStream = new FileOutputStream(fileOutputPath);
		byte[] buf = new byte[2048];
		int len;
		while ((len = in.read(buf, 0, buf.length)) >= 0) {
			outputStream.write(buf, 0, len);
		}
		outputStream.close();
		in.close();
	}

	/**
	 * description: 从minio下载对象到本地_通过minio直接输出
	 *
	 * @param minioClient    MinioClient客户端对象
	 * @param bucketName     桶名
	 * @param objectName     对象全名，如： yuantest/test/3639dfb5ceeb4ae290a3de68c8321cac.docx
	 * @param fileOutputPath 文件输出位置： 如：D:\aa\files\Java开发手册(黄山版).pdf
	 * @throws Exception
	 */
	public static void downloadToLocalByMinio(MinioClient minioClient, String bucketName, String objectName, String fileOutputPath) throws Exception {
		minioClient.downloadObject(DownloadObjectArgs
				.builder()
				.bucket(bucketName)
				//objectName
				.object(objectName)
				//outputpath,直接指定文件的输出位置+文件名即可
				.filename(fileOutputPath)
				.build());
	}

	public static InputStream  getObject (MinioClient minioClient, String bucketName, String fileName) throws Exception{
		return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());

	}
}
