package org.springblade.modules.resource.builder.oss;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.model.CannedAccessControlList;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectResult;
import org.springblade.core.oss.OssTemplate;
import org.springblade.core.oss.model.BladeFile;
import org.springblade.core.oss.model.OssFile;
import org.springblade.core.oss.props.OssProperties;
import org.springblade.core.oss.rule.OssRule;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class TencentOssTemplate implements OssTemplate {
    private final COSClient cosClient;
    private final OssProperties ossProperties;
    private final OssRule ossRule;

    public void makeBucket(String bucketName) {
        try {
            if (!this.bucketExists(bucketName)) {
                this.cosClient.createBucket(this.getBucketName(bucketName));
                this.cosClient.setBucketAcl(this.getBucketName(bucketName), CannedAccessControlList.PublicRead);
            }

        } catch (Throwable var3) {
            throw var3;
        }
    }

    public void removeBucket(String bucketName) {
        try {
            this.cosClient.deleteBucket(this.getBucketName(bucketName));
        } catch (Throwable var3) {
            throw var3;
        }
    }

    public boolean bucketExists(String bucketName) {
        try {
            return this.cosClient.doesBucketExist(this.getBucketName(bucketName));
        } catch (Throwable var3) {
            throw var3;
        }
    }

    public void copyFile(String bucketName, String fileName, String destBucketName) {
        try {
            this.cosClient.copyObject(this.getBucketName(bucketName), fileName, this.getBucketName(destBucketName), fileName);
        } catch (Throwable var5) {
            throw var5;
        }
    }

    public void copyFile(String bucketName, String fileName, String destBucketName, String destFileName) {
        try {
            this.cosClient.copyObject(this.getBucketName(bucketName), fileName, this.getBucketName(destBucketName), destFileName);
        } catch (Throwable var6) {
            throw var6;
        }
    }

    public OssFile statFile(String fileName) {
        try {
            return this.statFile(this.ossProperties.getBucketName(), fileName);
        } catch (Throwable var3) {
            throw var3;
        }
    }

    public OssFile statFile(String bucketName, String fileName) {
        try {
            ObjectMetadata stat = this.cosClient.getObjectMetadata(this.getBucketName(bucketName), fileName);
            OssFile ossFile = new OssFile();
            ossFile.setName(fileName);
            ossFile.setLink(this.fileLink(ossFile.getName()));
            ossFile.setHash(stat.getContentMD5());
            ossFile.setLength(stat.getContentLength());
            ossFile.setPutTime(stat.getLastModified());
            ossFile.setContentType(stat.getContentType());
            return ossFile;
        } catch (Throwable var5) {
            throw var5;
        }
    }

    public String filePath(String fileName) {
        try {
            return this.getOssHost().concat("/").concat(fileName);
        } catch (Throwable var3) {
            throw var3;
        }
    }

    public String filePath(String bucketName, String fileName) {
        try {
            return this.getOssHost(bucketName).concat("/").concat(fileName);
        } catch (Throwable var4) {
            throw var4;
        }
    }

    public String fileLink(String fileName) {
        try {
            return this.getOssHost().concat("/").concat(fileName);
        } catch (Throwable var3) {
            throw var3;
        }
    }

    public String fileLink(String bucketName, String fileName) {
        try {
            return this.getOssHost(bucketName).concat("/").concat(fileName);
        } catch (Throwable var4) {
            throw var4;
        }
    }

    public BladeFile putFile(MultipartFile file) {
        try {
            return this.putFile(this.ossProperties.getBucketName(), file.getOriginalFilename(), file);
        } catch (Throwable var3) {
            throw var3;
        }
    }

    public BladeFile putFile(String fileName, MultipartFile file) {
        try {
            return this.putFile(this.ossProperties.getBucketName(), fileName, file);
        } catch (Throwable var4) {
            throw var4;
        }
    }

    public BladeFile putFile(String bucketName, String fileName, MultipartFile file) {
        try {
            return this.putFile(bucketName, fileName, file.getInputStream());
        } catch (Throwable var5) {
            try {
                throw var5;
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public BladeFile putFile(String fileName, InputStream stream) {
        try {
            return this.putFile(this.ossProperties.getBucketName(), fileName, stream);
        } catch (Throwable var4) {
            throw var4;
        }
    }

    public BladeFile putFile(String bucketName, String fileName, InputStream stream) {
        try {
            return this.put(bucketName, stream, fileName, false);
        } catch (Throwable var5) {
            throw var5;
        }
    }

    public BladeFile put(String bucketName, InputStream stream, String key, boolean cover) {
        try {
            this.makeBucket(bucketName);
            String originalName = key;
            key = this.getFileName(key);
            if (cover) {
                this.cosClient.putObject(this.getBucketName(bucketName), key, stream, (ObjectMetadata)null);
            } else {
                PutObjectResult response = this.cosClient.putObject(this.getBucketName(bucketName), key, stream, (ObjectMetadata)null);
                int retry = 0;

                for(int retryCount = 5; StringUtils.isEmpty(response.getETag()) && retry < retryCount; ++retry) {
                    response = this.cosClient.putObject(this.getBucketName(bucketName), key, stream, (ObjectMetadata)null);
                }
            }

            BladeFile file = new BladeFile();
            file.setOriginalName(originalName);
            file.setName(key);
            file.setDomain(this.getOssHost(bucketName));
            file.setLink(this.fileLink(bucketName, key));
            return file;
        } catch (Throwable var9) {
            throw var9;
        }
    }

    public void removeFile(String fileName) {
        try {
            this.cosClient.deleteObject(this.getBucketName(), fileName);
        } catch (Throwable var3) {
            throw var3;
        }
    }

    public void removeFile(String bucketName, String fileName) {
        try {
            this.cosClient.deleteObject(this.getBucketName(bucketName), fileName);
        } catch (Throwable var4) {
            throw var4;
        }
    }

    public void removeFiles(List<String> fileNames) {
        try {
            fileNames.forEach(this::removeFile);
        } catch (Throwable var3) {
            throw var3;
        }
    }

    public void removeFiles(String bucketName, List<String> fileNames) {
        try {
            fileNames.forEach((fileName) -> {
                this.removeFile(this.getBucketName(bucketName), fileName);
            });
        } catch (Throwable var4) {
            throw var4;
        }
    }

    private String getBucketName() {
        return this.getBucketName(this.ossProperties.getBucketName());
    }

    private String getBucketName(String bucketName) {
        return this.ossRule.bucketName(bucketName).concat("-").concat(this.ossProperties.getAppId());
    }

    private String getFileName(String originalFilename) {
        return this.ossRule.fileName(originalFilename);
    }

    public String getOssHost(String bucketName) {
        return "https://" + this.cosClient.getClientConfig().getEndpointBuilder().buildGeneralApiEndpoint(this.getBucketName(bucketName));
    }

    public String getOssHost() {
        return this.getOssHost(this.ossProperties.getBucketName());
    }

    public TencentOssTemplate(final COSClient cosClient, final OssProperties ossProperties, final OssRule ossRule) {
        this.cosClient = cosClient;
        this.ossProperties = ossProperties;
        this.ossRule = ossRule;
    }
}

