"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
// This file is auto-generated, don't edit it
/**
 * This is for OpenApi Util
 */
const $tea = __importStar(require("@alicloud/tea-typescript"));
const tea_util_1 = __importDefault(require("@alicloud/tea-util"));
const kitx_1 = __importDefault(require("kitx"));
const querystring_1 = __importDefault(require("querystring"));
const crypto_1 = __importDefault(require("crypto"));
const PEM_BEGIN = "-----BEGIN PRIVATE KEY-----\n";
const PEM_END = "\n-----END PRIVATE KEY-----";
function replaceRepeatList(target, repeat, prefix) {
    if (prefix) {
        prefix = prefix + '.';
    }
    for (var i = 0; i < repeat.length; i++) {
        var item = repeat[i];
        let key = prefix + (i + 1);
        if (typeof item === 'undefined' || item == null) {
            continue;
        }
        if (Array.isArray(item)) {
            replaceRepeatList(target, item, key);
        }
        else if (item instanceof Object) {
            flatMap(target, item, key);
        }
        else {
            target[key] = item.toString();
        }
    }
}
function flatMap(target, params, prefix = '') {
    if (prefix) {
        prefix = prefix + '.';
    }
    params = toMap(params);
    let keys = Object.keys(params);
    for (let i = 0; i < keys.length; i++) {
        let key = keys[i];
        let value = params[key];
        key = prefix + key;
        if (typeof value === 'undefined' || value == null) {
            continue;
        }
        if (Array.isArray(value)) {
            replaceRepeatList(target, value, key);
        }
        else if (value instanceof Object) {
            flatMap(target, value, key);
        }
        else {
            target[key] = value.toString();
        }
    }
    return target;
}
function filter(value) {
    return value.replace(/[\t\n\r\f]/g, ' ');
}
function getCanonicalizedHeaders(headers) {
    const prefix = 'x-acs-';
    const keys = Object.keys(headers);
    const canonicalizedKeys = [];
    for (let i = 0; i < keys.length; i++) {
        const key = keys[i];
        if (key.startsWith(prefix)) {
            canonicalizedKeys.push(key);
        }
    }
    canonicalizedKeys.sort();
    var result = '';
    for (let i = 0; i < canonicalizedKeys.length; i++) {
        const key = canonicalizedKeys[i];
        result += `${key}:${filter(headers[key]).trim()}\n`;
    }
    return result;
}
function getCanonicalizedResource(uriPattern, query) {
    const keys = !query ? [] : Object.keys(query).sort();
    if (keys.length === 0) {
        return uriPattern;
    }
    var result = [];
    for (var i = 0; i < keys.length; i++) {
        const key = keys[i];
        result.push(`${key}=${query[key]}`);
    }
    return `${uriPattern}?${result.join('&')}`;
}
function getAuthorizationQueryString(query) {
    let canonicalQueryArray = [];
    const keys = !query ? [] : Object.keys(query).sort();
    for (let i = 0; i < keys.length; i++) {
        const key = keys[i];
        let param = key + '=';
        if (typeof query[key] !== 'undefined' && query[key] !== null) {
            param = param + encode(query[key]);
        }
        canonicalQueryArray.push(param);
    }
    return canonicalQueryArray.join('&');
}
function getAuthorizationHeaders(header) {
    let canonicalheaders = "";
    let tmp = {};
    const keys = !header ? [] : Object.keys(header);
    for (let i = 0; i < keys.length; i++) {
        const key = keys[i];
        const lowerKey = keys[i].toLowerCase();
        if (lowerKey.startsWith("x-acs-") || lowerKey === "host" || lowerKey === "content-type") {
            if (tmp[lowerKey]) {
                tmp[lowerKey].push((header[key] || "").trim());
            }
            else {
                tmp[lowerKey] = [(header[key] || "").trim()];
            }
        }
    }
    var hsKeys = Object.keys(tmp).sort();
    for (let i = 0; i < hsKeys.length; i++) {
        const hsKey = hsKeys[i];
        let listSort = tmp[hsKey].sort();
        canonicalheaders += `${hsKey}:${listSort.join(",")}\n`;
    }
    return { canonicalheaders, hsKeys };
}
function encode(str) {
    var result = encodeURIComponent(str);
    return result.replace(/!/g, '%21')
        .replace(/'/g, '%27')
        .replace(/\(/g, '%28')
        .replace(/\)/g, '%29')
        .replace(/\*/g, '%2A');
}
function normalize(params) {
    var list = [];
    var flated = {};
    flatMap(flated, params);
    var keys = Object.keys(flated).sort();
    for (let i = 0; i < keys.length; i++) {
        var key = keys[i];
        var value = flated[key];
        list.push([encode(key), encode(value)]);
    }
    return list;
}
function canonicalize(normalized) {
    var fields = [];
    for (var i = 0; i < normalized.length; i++) {
        var [key, value] = normalized[i];
        fields.push(key + '=' + value);
    }
    return fields.join('&');
}
function isModelClass(t) {
    if (!t) {
        return false;
    }
    return typeof t.types === 'function' && typeof t.names === 'function';
}
function isObjectOrArray(t) {
    return Array.isArray(t) || (t instanceof Object && typeof t !== 'function');
}
function toMap(input) {
    if (!isObjectOrArray(input)) {
        return null;
    }
    else if (input instanceof $tea.Model) {
        return $tea.toMap(input);
    }
    else if (input && input.toMap && typeof input.toMap === 'function') {
        // 解决跨版本 Model 不互认的问题
        return input.toMap();
    }
    else if (Array.isArray(input)) {
        const result = [];
        input.forEach((value) => {
            if (isObjectOrArray(value)) {
                result.push(toMap(value));
            }
            else {
                result.push(value);
            }
        });
        return result;
    }
    else if (input instanceof Object) {
        const result = {};
        Object.entries(input).forEach(([key, value]) => {
            if (isObjectOrArray(value)) {
                result[key] = toMap(value);
            }
            else {
                result[key] = value;
            }
        });
        return result;
    }
}
class Client {
    /**
     * Convert all params of body other than type of readable into content
     * @param input source Model
     * @param output target Model
     * @return void
     */
    static convert(input, output) {
        if (!output) {
            return;
        }
        let inputModel = Object.assign({}, input);
        let constructor = output.constructor;
        let types = constructor.types();
        // let constructor = <any>output.constructor;
        for (let key of Object.keys(constructor.names())) {
            if (inputModel[key] !== null && inputModel[key] !== undefined) {
                if (isModelClass(types[key])) {
                    output[key] = new types[key](output[key]);
                    Client.convert(inputModel[key], output[key]);
                }
                else if (types[key] && types[key].type === 'array') {
                    output[key] = inputModel[key].map(function (d) {
                        if (isModelClass(types[key].itemType)) {
                            var item = new types[key].itemType({});
                            Client.convert(d, item);
                            return item;
                        }
                        return d;
                    });
                }
                else if (types[key] && types[key].type === 'map') {
                    output[key] = {};
                    Object.keys(inputModel[key]).map(function (d) {
                        if (isModelClass(types[key].valueType)) {
                            var item = new types[key].valueType({});
                            Client.convert(inputModel[key][d], item);
                            output[key][d] = item;
                        }
                        else {
                            output[key][d] = inputModel[key][d];
                        }
                    });
                }
                else {
                    output[key] = inputModel[key];
                }
            }
        }
    }
    /**
     * Get the string to be signed according to request
     * @param request  which contains signed messages
     * @return the signed string
     */
    static getStringToSign(request) {
        const method = request.method;
        const accept = request.headers['accept'];
        const contentMD5 = request.headers['content-md5'] || '';
        const contentType = request.headers['content-type'] || '';
        const date = request.headers['date'] || '';
        const header = `${method}\n${accept}\n${contentMD5}\n${contentType}\n${date}\n`;
        const canonicalizedHeaders = getCanonicalizedHeaders(request.headers);
        const canonicalizedResource = getCanonicalizedResource(request.pathname, request.query);
        return `${header}${canonicalizedHeaders}${canonicalizedResource}`;
    }
    /**
     * Get signature according to stringToSign, secret
     * @param stringToSign  the signed string
     * @param secret accesskey secret
     * @return the signature
     */
    static getROASignature(stringToSign, secret) {
        const utf8Buff = Buffer.from(stringToSign, 'utf8');
        return kitx_1.default.sha1(utf8Buff, secret, 'base64');
    }
    /**
     * Parse filter into a form string
     * @param filter object
     * @return the string
     */
    static toForm(filter) {
        if (!filter) {
            return '';
        }
        let target = {};
        flatMap(target, filter);
        return tea_util_1.default.toFormString(target);
    }
    /**
     * Get timestamp
     * @return the timestamp string
     */
    static getTimestamp() {
        let date = new Date();
        let YYYY = date.getUTCFullYear();
        let MM = kitx_1.default.pad2(date.getUTCMonth() + 1);
        let DD = kitx_1.default.pad2(date.getUTCDate());
        let HH = kitx_1.default.pad2(date.getUTCHours());
        let mm = kitx_1.default.pad2(date.getUTCMinutes());
        let ss = kitx_1.default.pad2(date.getUTCSeconds());
        return `${YYYY}-${MM}-${DD}T${HH}:${mm}:${ss}Z`;
    }
    /**
     * Parse filter into a object which's type is map[string]string
     * @param filter query param
     * @return the object
     */
    static query(filter) {
        if (!filter) {
            return {};
        }
        let ret = {};
        flatMap(ret, filter);
        return ret;
    }
    /**
     * Get signature according to signedParams, method and secret
     * @param signedParams params which need to be signed
     * @param method http method e.g. GET
     * @param secret AccessKeySecret
     * @return the signature
     */
    static getRPCSignature(signedParams, method, secret) {
        var normalized = normalize(signedParams);
        var canonicalized = canonicalize(normalized);
        var stringToSign = `${method}&${encode('/')}&${encode(canonicalized)}`;
        const key = secret + '&';
        return kitx_1.default.sha1(stringToSign, key, 'base64');
    }
    /**
     * Parse array into a string with specified style
     * @param array the array
     * @param prefix the prefix string
     * @style specified style e.g. repeatList
     * @return the string
     */
    static arrayToStringWithSpecifiedStyle(array, prefix, style) {
        if (!array) {
            return '';
        }
        if (style === 'repeatList') {
            let target = {};
            replaceRepeatList(target, array, prefix);
            return querystring_1.default.stringify(target, '&&');
        }
        else if (style === 'json') {
            return JSON.stringify(toMap(array));
        }
        else if (style === 'simple') {
            return array.join(',');
        }
        else if (style === 'spaceDelimited') {
            return array.join(' ');
        }
        else if (style === 'pipeDelimited') {
            return array.join('|');
        }
        else {
            return '';
        }
    }
    /**
     * Transform input as map.
     */
    static parseToMap(input) {
        return toMap(input);
    }
    static getEndpoint(endpoint, serverUse, endpointType) {
        if (endpointType == "internal") {
            let strs = endpoint.split(".");
            strs[0] += "-internal";
            endpoint = strs.join(".");
        }
        if (serverUse && endpointType == "accelerate") {
            return "oss-accelerate.aliyuncs.com";
        }
        return endpoint;
    }
    /**
    * Encode raw with base16
    * @param raw encoding data
    * @return encoded string
    */
    static hexEncode(raw) {
        return raw.toString("hex");
    }
    /**
     * Hash the raw data with signatureAlgorithm
     * @param raw hashing data
     * @param signatureAlgorithm the autograph method
     * @return hashed bytes
    */
    static hash(raw, signatureAlgorithm) {
        if (signatureAlgorithm === "ACS3-HMAC-SHA256" || signatureAlgorithm === "ACS3-RSA-SHA256") {
            const obj = crypto_1.default.createHash('sha256');
            obj.update(raw);
            return obj.digest();
        }
        else if (signatureAlgorithm == "ACS3-HMAC-SM3") {
            const obj = crypto_1.default.createHash('sm3');
            obj.update(raw);
            return obj.digest();
        }
    }
    static signatureMethod(secret, source, signatureAlgorithm) {
        if (signatureAlgorithm === "ACS3-HMAC-SHA256") {
            const obj = crypto_1.default.createHmac('sha256', secret);
            obj.update(source);
            return obj.digest();
        }
        else if (signatureAlgorithm === "ACS3-HMAC-SM3") {
            const obj = crypto_1.default.createHmac('sm3', secret);
            obj.update(source);
            return obj.digest();
        }
        else if (signatureAlgorithm === "ACS3-RSA-SHA256") {
            if (!secret.startsWith(PEM_BEGIN)) {
                secret = PEM_BEGIN + secret;
            }
            if (!secret.endsWith(PEM_END)) {
                secret = secret + PEM_END;
            }
            var signerObject = crypto_1.default.createSign("RSA-SHA256");
            signerObject.update(source);
            var signature = signerObject.sign({ key: secret, padding: crypto_1.default.constants.RSA_PKCS1_PADDING });
            return signature;
        }
    }
    /**
     * Get the authorization
     * @param request request params
     * @param signatureAlgorithm the autograph method
     * @param payload the hashed request
     * @param acesskey the acesskey string
     * @param accessKeySecret the accessKeySecret string
     * @return authorization string
     */
    static getAuthorization(request, signatureAlgorithm, payload, acesskey, accessKeySecret) {
        const canonicalURI = (request.pathname || "").replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
        const method = request.method;
        const canonicalQueryString = getAuthorizationQueryString(request.query);
        const tuple = getAuthorizationHeaders(request.headers);
        const canonicalheaders = tuple["canonicalheaders"];
        const signedHeaders = tuple["hsKeys"];
        const canonicalRequest = method + "\n" + canonicalURI + "\n" + canonicalQueryString + "\n" + canonicalheaders + "\n" +
            signedHeaders.join(";") + "\n" + payload;
        let raw = Buffer.from(canonicalRequest);
        const stringToSign = signatureAlgorithm + "\n" + Client.hexEncode(Client.hash(raw, signatureAlgorithm));
        const signature = Client.hexEncode(Client.signatureMethod(accessKeySecret, stringToSign, signatureAlgorithm));
        const auth = `${signatureAlgorithm} Credential=${acesskey},SignedHeaders=${signedHeaders.join(';')},Signature=${signature}`;
        return auth;
    }
    static getEncodePath(path) {
        if (typeof path === 'undefined' || path === null) {
            return '';
        }
        let strs = path.split('/');
        for (let i = 0; i < strs.length; i++) {
            strs[i] = encode(strs[i]);
        }
        return strs.join('/');
    }
    static getEncodeParam(param) {
        if (typeof param === 'undefined' || param === null) {
            return '';
        }
        return encode(param);
    }
    /**
     * Transform a map to a flat style map where keys are prefixed with length info.
     * Map keys are transformed from "key" to "#length#key" format.
     * @param object the input object (can be a Model, Array, Map, or other types)
     * @return the transformed object
     */
    static mapToFlatStyle(object) {
        if (object === null || object === undefined) {
            return object;
        }
        if (Array.isArray(object)) {
            const list = [];
            for (let i = 0; i < object.length; i++) {
                list.push(Client.mapToFlatStyle(object[i]));
            }
            return list;
        }
        else if (object instanceof $tea.Model || (object && object.toMap && typeof object.toMap === 'function')) {
            // Handle TeaModel instances
            const map = object instanceof $tea.Model ? $tea.toMap(object) : object.toMap();
            const result = {};
            for (const key of Object.keys(map)) {
                const value = map[key];
                if (value !== null && value !== undefined && typeof value === 'object' && !Array.isArray(value) && !(value instanceof $tea.Model) && !(value.toMap && typeof value.toMap === 'function')) {
                    // It's a plain Map/object
                    const flatMap = {};
                    for (const entryKey of Object.keys(value)) {
                        flatMap[`#${entryKey.length}#${entryKey}`] = Client.mapToFlatStyle(value[entryKey]);
                    }
                    result[key] = flatMap;
                }
                else {
                    result[key] = Client.mapToFlatStyle(value);
                }
            }
            return result;
        }
        else if (typeof object === 'object') {
            // Handle plain Map/object
            const flatMap = {};
            for (const key of Object.keys(object)) {
                flatMap[`#${key.length}#${key}`] = Client.mapToFlatStyle(object[key]);
            }
            return flatMap;
        }
        return object;
    }
}
exports.default = Client;
//# sourceMappingURL=client.js.map