/**
 * ali-oss模块
 * @date 2022-03
 * @author 何华东
 */

import { logger } from 'mslib';
import { Stream } from 'stream';
import { Singleton } from 'typescript-ioc';
import { IocConfigProvider } from './Config';
import { ConfigCenterConfigProvider } from './ConfigCenter';
import Contants from './Contants';
import { ListQuery, ListResponse, OssService } from "./OssService";
const OSS = require('ali-oss');

/**
 * ali-oss客户端实例
 * 
 * 如已引用配置依赖[NsConfig](https://me.keytop.cn/service/config)将会自动创建该实例
 * 
 * ```
 * import { aliOss, aliOssClient } from "refs/nslib";
 * 
 * let res = await aliOssClient.put(`${filename}`, buffer);
 * aliOss.throwIfUrlIsEmpty(res);
 * let url = res.url;
 * ```
 * @see [ali-oss](https://www.npmjs.com/package/ali-oss)
 */
export let aliOssClient = null;

init();

async function init() {
    try {
        //配置优先级: 1.本地配置 2.配置中心
        let config = IocConfigProvider.getAliOssConfig() || await ConfigCenterConfigProvider.getAliOssConfig();
        if (!config) return;

        //默认启用安全配置secure(使用https文件地址)
        config = Object.assign({ secure: true }, config);
        aliOssClient = new OSS(config);

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

/**
 * ali-oss响应类
 */
type AliOssResponse = {
    [prop: string]: any;

    res: {
        status: number;
        statusCode: number;
        statusMessage: string;
    };
}

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

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

        let res: AliOssResponse = await aliOssClient.put(name, file);
        
        logger.info(`上传对象到ali-oss成功,对象名:${name},地址:${res.url}`);
         
        return res.url;
    }

    /** @inheritdoc */
    async list(query?: ListQuery): Promise<ListResponse> {
        let res: AliOssResponse = await aliOssClient.list({
            prefix: query?.prefix,
            marker: query?.marker,
            delimiter: query?.delimiter,
            'max-keys': query?.maxKeys,
        });

        return res['objects'];
    }

    /** @inheritdoc */
    async delete(name: string) {
        //删除成功或对象名匹配不到Status都为204
        return await aliOssClient.delete(name);
    }
}