package cn.cloud.util.file;

import java.io.InputStream;
import java.net.URLDecoder;
import java.util.Objects;
import org.springframework.web.multipart.MultipartFile;

import cn.cloud.common.StorageConst;
import cn.cloud.util.common.StorageAccessUtil;
import cn.util.core.IsKit;
import cn.util.core.LogKit;
import io.minio.BucketExistsArgs;
import io.minio.GetObjectArgs;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import io.minio.http.Method;

/**
 * minio文件上传工具类
 */
public class MinioUtil 
{
	private static String minioUrl;
	private static String minioName;
	private static String minioPass;
	private static String bucketName;

	public static void setMinioUrl(String minioUrl) {
		MinioUtil.minioUrl = minioUrl;
	}

	public static void setMinioName(String minioName) {
		MinioUtil.minioName = minioName;
	}

	public static void setMinioPass(String minioPass) {
		MinioUtil.minioPass = minioPass;
	}

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

	public static String getMinioUrl() {
		return minioUrl;
	}

	public static String getBucketName() {
		return bucketName;
	}

	private static MinioClient minioClient = null;

	/**
	 * 上传文件
	 * @param file
	 * @return
	 */
	public static String upload(MultipartFile file, String bizPath, String customBucket) {
		String file_url = "";
		String newBucket = bucketName;
		if(IsKit.isNotNullOrEmpty(customBucket)){
			newBucket = customBucket;
		}
		try {
			initMinio(minioUrl, minioName,minioPass);
			// 检查存储桶是否已经存在
			//4.0.0OK if(minioClient.bucketExists(newBucket)) {
			//8.4.5 待验证
			if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(newBucket).build())){
				LogKit.info("Bucket already exists.");
			} else {
				// 创建一个名为ota的存储桶
				//4.0.0OK  minioClient.makeBucket(newBucket);
				//8.4.5 待验证
				minioClient.makeBucket(MakeBucketArgs.builder().bucket(newBucket).build());

				LogKit.info("create a new bucket.");
			}
			InputStream stream = file.getInputStream();
			// 获取文件名
			String orgName = file.getOriginalFilename();
			if("".equals(orgName)){
				orgName=file.getName();
			}
			orgName = StorageAccessUtil.getFileName(orgName);
			String objectName = bizPath+"/"+orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.indexOf("."));

			// 使用putObject上传一个本地文件到存储桶中。
			//4.0.0OK minioClient.putObject(newBucket,objectName, stream,stream.available(),"application/octet-stream");
			//8.4.5 待验证
			minioClient.putObject(
					PutObjectArgs.builder().bucket(newBucket)
					.object(objectName)
					.stream(stream,stream.available(), -1)
					.contentType("application/octet-stream")
					.build());

			stream.close();
			file_url = minioUrl+newBucket+"/"+objectName;
		}catch (Exception e){
			LogKit.info(e.getMessage(), e);
		}
		return file_url;
	}

	/**
	 * 文件上传
	 * @param file
	 * @param bizPath
	 * @return
	 */
	public static String upload(MultipartFile file, String bizPath) {
		return  upload(file,bizPath,null);
	}

	/**
	 * 获取文件流
	 * @param bucketName
	 * @param objectName
	 * @return
	 */
	public static InputStream getMinioFile(String bucketName,String objectName){
		InputStream inputStream = null;
		try {
			initMinio(minioUrl, minioName, minioPass);
			//4.0.0OK inputStream = minioClient.getObject(bucketName, objectName);
			//8.4.5 待验证
			GetObjectArgs.Builder builder = GetObjectArgs.builder();
			builder.bucket(bucketName);
			builder.object(objectName);	 
			GetObjectArgs objectArgs = builder.build();
			inputStream = minioClient.getObject(objectArgs);	
		} catch (Exception e) {
			LogKit.info("文件获取失败" + e.getMessage());
		}
		return inputStream;
	}

	/**
	 * 删除文件
	 * @param bucketName
	 * @param objectName
	 * @throws Exception
	 */
	public static void removeObject(String bucketName, String objectName) {
		try {
			initMinio(minioUrl, minioName,minioPass);
			// 4. 删除存储桶
			//4.0.0OK minioClient.removeObject(bucketName, objectName);
			//8.4.5 待验证
			RemoveObjectArgs.Builder builder = RemoveObjectArgs.builder();
			builder.bucket(bucketName);
			builder.object(objectName);
			RemoveObjectArgs removeObjectArgs = builder.build();
			minioClient.removeObject(removeObjectArgs);
		}catch (Exception e){
			LogKit.info("文件删除失败" + e.getMessage());
		}
	}

	/**
	 * 获取文件外链
	 * @param bucketName
	 * @param objectName
	 * @param expires
	 * @return
	 */
	public static String getObjectURL(String bucketName, String objectName, Integer expires) {
		initMinio(minioUrl, minioName,minioPass);
		try{
			//获取可下载的url
			//4.0.0OK String url = minioClient.presignedGetObject(bucketName, objectName, expires);
			//8.4.5 待验证
			String url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
					.method(Method.GET)
					.bucket(bucketName)
					.object(objectName)
					.expiry(Objects.isNull(expires) ? StorageConst.DEFAULT_EXPIRY_TIME : expires)
					.build()
					);
			return URLDecoder.decode(url,"UTF-8");
		}catch (Exception e){
			LogKit.info("文件路径获取失败" + e.getMessage());
		}
		return null;
	}

	/**
	 * 初始化客户端
	 * @param minioUrl
	 * @param minioName
	 * @param minioPass
	 * @return
	 */
	private static MinioClient initMinio(String minioUrl, String minioName,String minioPass) {
		if (minioClient == null) {
			try {
				//4.0.0OK minioClient = new MinioClient(minioUrl, minioName,minioPass);
				//8.4.5 待验证
				MinioClient.builder().endpoint(minioUrl)
				.credentials(minioName, minioPass)
				.build();
			} catch (Exception e) {
				LogKit.info(e);
			}
		}
		return minioClient;
	}

	/**
	 * 上传文件到minio
	 * @param stream
	 * @param relativePath
	 * @return
	 */
	public static String upload(InputStream stream,String relativePath) throws Exception 
	{
		initMinio(minioUrl, minioName,minioPass);
		// 2.2 创建存储桶my-bucketname-in-eu 并指定区域为eu-west-1
		//4.0.0OK if(minioClient.bucketExists(bucketName)) {
		//8.4.5 待验证
		if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())){
			LogKit.info("Bucket already exists.");
		} else {
			// 创建一个名为ota的存储桶
			//4.0.0OK  minioClient.makeBucket(bucketName);
			//8.4.5 待验证
			minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());

			LogKit.info("create a new bucket.");
		}
		//4.0.0OK minioClient.putObject(bucketName,relativePath, stream, stream.available(),"application/octet-stream");
		//8.4.5 待验证
		minioClient.putObject(
				PutObjectArgs.builder().bucket(bucketName)
				.object(relativePath)
				.stream(stream,stream.available(), -1)
				.contentType("application/octet-stream")
				.build());

		stream.close();
		return minioUrl+bucketName+"/"+relativePath;
	}
}
