package com.tourism.common.huaweicloud.obs.wrapper;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.obs.services.ObsClient;
import com.obs.services.model.ObjectMetadata;
import com.tourism.common.huaweicloud.obs.config.HuaweicloudObsProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

/**
 * 封装的华为云OBS客户端模板类。
 *
 * @author 吃饭睡觉
 * @date 2024-09-06
 */
@Slf4j
public class HuaweicloudObsTemplate {

    private static final String TMP_DIR = System.getProperty("java.io.tmpdir") + File.separator;
    private final HuaweicloudObsProperties properties;
    private final ObsClient client;

    public HuaweicloudObsTemplate(HuaweicloudObsProperties properties, ObsClient client) {
        super();
        this.properties = properties;
        this.client = client;
    }

    /**
     * 判断bucket是否存在。
     *
     * @param bucketName 桶名称。
     * @return 存在返回true，否则false。
     */
    public boolean bucketExists(String bucketName) {
        try {
            return client.headBucket(bucketName);
        } catch (Exception e) {
            log.error("", e);
        }
        return false;
    }

    /**
     * 创建桶。
     *
     * @param bucketName 桶名称。
     */
    public void makeBucket(String bucketName) {
        if (!client.headBucket(bucketName)) {
            client.createBucket(bucketName);
        }
    }

    /**
     * 存放对象。
     *
     * @param bucketName 桶名称。
     * @param objectName 对象名称。
     * @param filename   本地上传的文件名称。
     */
    public void putObject(String bucketName, String objectName, String filename) {
        client.putObject(bucketName, objectName, new File(filename));
    }

    /**
     * 存放对象。桶名称为配置中的桶名称。
     *
     * @param objectName 对象名称。
     * @param filename   本地上传的文件名称。
     */
    public void putObject(String objectName, String filename) {
        this.putObject(properties.getBucketName(), objectName, filename);
    }

    /**
     * 读取输入流并存放。
     *
     * @param bucketName 桶名称。
     * @param objectName 对象名称。
     * @param stream     读取后上传的文件流。
     */
    public void putObject(String bucketName, String objectName, InputStream stream) {
        client.putObject(bucketName, objectName, stream);
    }

    /**
     * 读取输入流并存放。
     *
     * @param objectName 对象名称。
     * @param stream     读取后上传的文件流。
     */
    public void putObject(String objectName, InputStream stream) {
        this.putObject(properties.getBucketName(), objectName, stream);
    }

    /**
     * 移除对象。
     *
     * @param bucketName 桶名称。
     * @param objectName 对象名称。
     */
    public void removeObject(String bucketName, String objectName) {
        client.deleteObject(bucketName, objectName);
    }

    /**
     * 移除对象。桶名称为配置中的桶名称。
     *
     * @param objectName 对象名称。
     */
    public void removeObject(String objectName) {
        this.removeObject(properties.getBucketName(), objectName);
    }

    /**
     * 获取文件输入流。
     *
     * @param bucket     桶名称。
     * @param objectName 对象名称。
     * @return 文件的输入流。
     */
    public InputStream getStream(String bucket, String objectName) {
        return client.getObject(bucket, objectName).getObjectContent();
    }

    /**
     * 获取文件输入流。
     *
     * @param objectName 对象名称。
     * @return 文件的输入流。
     */
    public InputStream getStream(String objectName) {
        return this.getStream(properties.getBucketName(), objectName);
    }

    /**
     * 获取存储的文件对象。
     *
     * @param bucket     桶名称。
     * @param objectName 对象名称。
     * @return 读取后存储到文件的文件对象。
     */
    public File getFile(String bucket, String objectName) throws IOException {
        InputStream in = getStream(bucket, objectName);
        File dir = new File(TMP_DIR);
        if (!dir.exists() || dir.isFile()) {
            dir.mkdirs();
        }
        File file = new File(TMP_DIR + objectName);
        FileUtils.copyInputStreamToFile(in, file);
        in.close();
        return file;
    }

    /**
     * 获取存储的文件对象。桶名称为配置中的桶名称。
     *
     * @param objectName 对象名称。
     * @return 读取后存储到文件的文件对象。
     */
    public File getFile(String objectName) throws IOException {
        return this.getFile(properties.getBucketName(), objectName);
    }

    /**
     * 获取对象状态信息。
     *
     * @param bucketName 桶名称。
     * @param objectName 对象名称。
     * @return 对象状态和meta信息。
     */
    public ObjectMetadata statObject(String bucketName, String objectName) {
        return client.getObjectMetadata(bucketName, objectName);
    }

    /**
     * 获取对象状态信息。桶名称为配置中的桶名称。
     *
     * @param objectName 对象名称。
     * @return 对象状态和meta信息。
     */
    public ObjectMetadata statObject(String objectName) {
        return client.getObjectMetadata(properties.getBucketName(), objectName);
    }

    private Date getExpiredDate() {
        return DateUtil.date().offset(DateField.SECOND, properties.getExpireSeconds());
    }
}
