/**
 * 华为云对象存储服务obs
 * @date 2022-08-09 11:55:58
 * @author 黄家维
 */

import { logger } from "mslib";
import { Readable, Stream } from "stream";
import { Singleton } from "typescript-ioc";
import { IocConfigProvider } from "./Config";
import Contants from "./Contants";
import { ListQuery, ListResponse, OssService } from "./OssService";
import { ConfigCenterConfigProvider } from './ConfigCenter';

/**
 * 非标桶
 */
let non_standard_bucket = 'ddd-nonstandar';

/**
 * 文件根地址
 */
let accessBaseUrl = 'https://dddfile.keytop.cn';

/**
 * 华为obs客户端实例
 * 
 * @see [huawei-obs](https://support.huaweicloud.com/api-obs_nodejs_sdk_api_zh/obs_39_0101.html)
 */
export let obsClient = null;
let config = null;

init();

async function init() {
    let ObsClient = null;

    //检测插件
    try {
        ObsClient = require('esdk-obs-nodejs');
    } catch (error) { }

    if (!ObsClient) return;

    try {
        config = IocConfigProvider.getHuaweiObsConfig() || await ConfigCenterConfigProvider.getHuaweiObsConfig();
        if(!config) return;

        obsClient = new ObsClient(config);

        non_standard_bucket = config.bucket;

        logger.info(`huawei-obs客户端实例创建成功,server:${config.server},access_key_id:${config.access_key_id}`);
    } catch (error) {
        logger.error('huawei-obs客户端实例创建失败', error);
    }
}

/**
 * 华为obs响应
 */
export class HuaWeiObsResponse {
    /**
     * 判断华为接口响应是否为成功
     */
    static statusIsSuccess(status: number) {
        return status < 300;
    }

    CommonMsg: {
        Status: number,
        Code: string,
        Message: string,
        HostId: string,
        RequestId: string,
        InterfaceResult: any,
        Id2: string
    };

    InterfaceResult: {
        ContentLength: string,
        Date: string,
        Reserved: undefined,
        RequestId: string,
        Id2: string,
        ETag: string,
        Contents: any
    };
}

/**
 * 华为obs服务
 * 
 * @see {@link OssService}
 */
@Singleton
export class HuaWeiObsService implements OssService {
    /** @inheritdoc */
    getRootPath() {
        return Contants.P_ID || IocConfigProvider.getBasicConfig()?.tapdId || 'non-standard';
    }

    /** @inheritdoc */
    put(file: string | Buffer | Stream, name: string): Promise<string> {
        return new Promise((resolve, reject) => {
            //不包含根目录，自动加上根目录
            if (name.indexOf('/', 1) === -1) name = `${this.getRootPath()}${name.startsWith('/') ? '' : '/'}${name}`;

            let opt : any = {};
            if(typeof file === 'string'){
                opt.SourceFile = file;
            }else {
                opt.Body = Buffer.isBuffer(file) ? Readable.from(file) : file;
            }

            obsClient.putObject({
                Bucket: non_standard_bucket,
                Key: name,
                ...opt
            }, (err: any, res: HuaWeiObsResponse) => {
                if (err) {
                    reject(err);
                    return;
                }

                if (!HuaWeiObsResponse.statusIsSuccess(res.CommonMsg.Status)) {
                    reject(res);
                    return;
                }
                
                let accessUrl = null;
                if(config.bucket === 'ddd-nonstandar'){
                    accessUrl =`${accessBaseUrl}/${name}`;
                }else {
                    accessUrl = `https://${config.bucket}.${config.server}/${name}`;
                }

                logger.info(`上传对象到华为obs成功,对象名:${name},地址:${accessUrl}`);
                resolve(accessUrl);
            });
        })
    }

    /** @inheritdoc */
    list(query?: ListQuery): Promise<ListResponse> {
        return new Promise((resolve, reject) => {
            obsClient.listObjects({
                Bucket: non_standard_bucket,
                Prefix: query?.prefix,
                MaxKeys: query?.maxKeys
            }, (err: any, res: HuaWeiObsResponse) => {
                if (err) reject(err);
                if (!HuaWeiObsResponse.statusIsSuccess(res?.CommonMsg.Status)) {
                    reject(res);
                }

                let contents: {
                    Key: string,
                    LastModified: string,
                    ETag: string,
                    Size: string,
                    Type: string,
                    StorageClass: string
                }[] = res.InterfaceResult.Contents;

                resolve(contents?.map(s => { return { name: s.Key, ...s } }));
            });
        })
    }

    /** @inheritdoc */
    delete(name: string): Promise<any> {
        return new Promise((resolve, reject) => {
            obsClient.deleteObject({
                Bucket: non_standard_bucket,
                Key: name
            }, (err: any, res: HuaWeiObsResponse) => {
                if (err) reject(err);
                if (!HuaWeiObsResponse.statusIsSuccess(res?.CommonMsg.Status)) {
                    reject(res);
                }
                //删除成功或对象名匹配不到Status都为204
                resolve(res);
            });
        })
    }
} 