import { createHmac, createHash } from 'crypto';
import got from 'got';

/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0

THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.

See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */

function __awaiter(thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
}

function __generator(thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
}

function logger(topic, content) {
    console.log("[DEBUG] " + topic + ": " + content + " ");
}
function stringifyPrimitive(v) {
    switch (typeof v) {
        case 'string':
            return v;
        case 'boolean':
            return v ? 'true' : 'false';
        case 'number':
            return isFinite(v) ? v : '';
        default:
            return '';
    }
}
function safeUrlEncode(str) {
    return encodeURIComponent(str)
        .replace(/!/g, '%21')
        .replace(/'/g, '%27')
        .replace(/\(/g, '%28')
        .replace(/\)/g, '%29')
        .replace(/\*/g, '%2A');
}
function querystring(obj) {
    var sep = '&';
    var eq = '=';
    if (!obj)
        return '';
    if (obj && typeof obj === 'object') {
        return Object.keys(obj)
            .map(function (k) {
            var ks = safeUrlEncode(stringifyPrimitive(k)) + eq;
            if (Array.isArray(obj[k])) {
                return obj[k]
                    .map(function (v) {
                    return ks + safeUrlEncode(stringifyPrimitive(v));
                })
                    .join(sep);
            }
            else {
                return ks + safeUrlEncode(stringifyPrimitive(obj[k]));
            }
        })
            .filter(Boolean)
            .join(sep);
    }
    return '';
}
function sha1(str, key) {
    return createHmac('sha1', key)
        .update(str)
        .digest('hex');
}
function hash(str, algorithm) {
    return createHash(algorithm)
        .update(str)
        .digest('hex');
}
function sortObjectKey(obj) {
    var list = [];
    Object.keys(obj).forEach(function (key) {
        if (obj.hasOwnProperty(key)) {
            list.push(key);
        }
    });
    return list.sort(function (a, b) {
        a = a.toLowerCase();
        b = b.toLowerCase();
        return a === b ? 0 : a > b ? 1 : -1;
    });
}
function sortHeaderKey(obj) {
    var list = [];
    Object.keys(obj).forEach(function (key) {
        var lowerKey = key.toLowerCase();
        if (obj.hasOwnProperty(key) &&
            (lowerKey === 'content-type' ||
                lowerKey === 'content-md5' ||
                lowerKey === 'host' ||
                lowerKey[0] === 'x')) {
            list.push(key);
        }
    });
    return list.sort(function (a, b) {
        a = a.toLowerCase();
        b = b.toLowerCase();
        return a === b ? 0 : a > b ? 1 : -1;
    });
}
function stringifyObject(obj, sortKeyMethod) {
    var list = [];
    var keyList = sortKeyMethod(obj);
    keyList.forEach(function (key) {
        var val = obj[key] === undefined || obj[key] === null ? '' : '' + obj[key];
        key = key.toLowerCase();
        key = safeUrlEncode(key);
        val = safeUrlEncode(val) || '';
        list.push(key + '=' + val);
    });
    return list.join('&');
}
function tencentSign(_a) {
    var secretId = _a.secretId, secretKey = _a.secretKey, method = _a.method, path = _a.path, parameters = _a.parameters, headers = _a.headers, expire = _a.expire;
    var now = Math.floor(Date.now() / 1000);
    var exp = now + Math.floor(expire / 1000);
    now = now - 60;
    // api only support sha1
    var ALGORITHM = 'sha1';
    var signTime = now + ';' + exp;
    var sortedHeader = sortHeaderKey(headers)
        .join(';')
        .toLowerCase();
    var sortedParameters = sortObjectKey(parameters)
        .join(';')
        .toLowerCase();
    // Refer to: https://cloud.tencent.com/document/product/614/12445
    // 1. SignKey
    var signKey = sha1(signTime, secretKey);
    // 2. HttpRequestInfo
    var formatString = [
        method.toLowerCase(),
        path,
        stringifyObject(parameters, sortObjectKey),
        stringifyObject(headers, sortHeaderKey),
        '',
    ].join('\n');
    //formatString = Buffer.from(formatString, 'utf8');
    // 3. StringToSign
    var stringToSign = [
        ALGORITHM,
        signTime,
        hash(formatString, ALGORITHM),
        '',
    ].join('\n');
    // 4. Signature
    var signature = sha1(stringToSign, signKey);
    // 步骤五：构造 Authorization
    var authorization = [
        'q-sign-algorithm=' + ALGORITHM,
        'q-ak=' + secretId,
        'q-sign-time=' + signTime,
        'q-key-time=' + signTime,
        'q-header-list=' + sortedHeader,
        'q-url-param-list=' + sortedParameters,
        'q-signature=' + signature,
    ].join('&');
    return authorization;
}

var Cls = /** @class */ (function () {
    function Cls(options) {
        this.options = options;
        this.options.region = this.options.region || 'ap-guangzhou';
        this.options.expire = this.options.expire || 300000;
    }
    /**
     * get logsets list
     */
    Cls.prototype.getLogsetList = function () {
        return __awaiter(this, void 0, void 0, function () {
            var res;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.request({
                            method: 'GET',
                            path: '/logsets',
                        })];
                    case 1:
                        res = _a.sent();
                        return [2 /*return*/, res];
                }
            });
        });
    };
    /**
     * get logset detail
     * @param logset_id string
     */
    Cls.prototype.getLogset = function (data) {
        return __awaiter(this, void 0, void 0, function () {
            var res;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.request({
                            method: 'GET',
                            path: '/logset',
                            query: data,
                        })];
                    case 1:
                        res = _a.sent();
                        return [2 /*return*/, res];
                }
            });
        });
    };
    /**
     * create logset
     * @param data
     */
    Cls.prototype.createLogset = function (data) {
        return __awaiter(this, void 0, void 0, function () {
            var res;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.request({
                            method: 'POST',
                            path: '/logset',
                            data: data,
                        })];
                    case 1:
                        res = _a.sent();
                        return [2 /*return*/, res];
                }
            });
        });
    };
    /**
     * update logset
     * @param data
     */
    Cls.prototype.updateLogset = function (data) {
        return __awaiter(this, void 0, void 0, function () {
            var res;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.request({
                            method: 'PUT',
                            path: '/logset',
                            data: data,
                        })];
                    case 1:
                        res = _a.sent();
                        return [2 /*return*/, res];
                }
            });
        });
    };
    /**
     * dalete logset
     * @param data
     */
    Cls.prototype.deleteLogset = function (data) {
        return __awaiter(this, void 0, void 0, function () {
            var res;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.request({
                            method: 'DELETE',
                            path: '/logset',
                            query: data,
                        })];
                    case 1:
                        res = _a.sent();
                        return [2 /*return*/, res];
                }
            });
        });
    };
    /**
     * create topic
     * @param data
     */
    Cls.prototype.createTopic = function (data) {
        return __awaiter(this, void 0, void 0, function () {
            var res;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.request({
                            method: 'POST',
                            path: '/topic',
                            data: data,
                        })];
                    case 1:
                        res = _a.sent();
                        return [2 /*return*/, res];
                }
            });
        });
    };
    /**
     * get topic
     * @param data
     */
    Cls.prototype.getTopic = function (data) {
        return __awaiter(this, void 0, void 0, function () {
            var res;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.request({
                            method: 'GET',
                            path: '/topic',
                            query: data,
                        })];
                    case 1:
                        res = _a.sent();
                        return [2 /*return*/, res];
                }
            });
        });
    };
    /**
     * get topic
     * @param data
     */
    Cls.prototype.getTopicList = function (data) {
        return __awaiter(this, void 0, void 0, function () {
            var res;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.request({
                            method: 'GET',
                            path: '/topics',
                            query: data,
                        })];
                    case 1:
                        res = _a.sent();
                        return [2 /*return*/, res];
                }
            });
        });
    };
    /**
     * update topic
     * @param data
     */
    Cls.prototype.updateTopic = function (data) {
        return __awaiter(this, void 0, void 0, function () {
            var res;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.request({
                            method: 'PUT',
                            path: '/topic',
                            data: data,
                        })];
                    case 1:
                        res = _a.sent();
                        return [2 /*return*/, res];
                }
            });
        });
    };
    /**
     * delete topic
     * @param data
     */
    Cls.prototype.deleteTopic = function (data) {
        return __awaiter(this, void 0, void 0, function () {
            var res;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.request({
                            method: 'DELETE',
                            path: '/topic',
                            query: data,
                        })];
                    case 1:
                        res = _a.sent();
                        return [2 /*return*/, res];
                }
            });
        });
    };
    Cls.prototype.getIndex = function (data) {
        return __awaiter(this, void 0, void 0, function () {
            var res;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.request({
                            method: 'GET',
                            path: '/index',
                            query: data,
                        })];
                    case 1:
                        res = _a.sent();
                        return [2 /*return*/, res];
                }
            });
        });
    };
    /**
     * update index
     * @param data
     */
    Cls.prototype.updateIndex = function (data) {
        return __awaiter(this, void 0, void 0, function () {
            var res;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.request({
                            method: 'PUT',
                            path: '/index',
                            data: data,
                        })];
                    case 1:
                        res = _a.sent();
                        return [2 /*return*/, res];
                }
            });
        });
    };
    Cls.prototype.searchLog = function (data) {
        return __awaiter(this, void 0, void 0, function () {
            var res;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.request({
                            method: 'GET',
                            path: '/searchlog',
                            query: data,
                        })];
                    case 1:
                        res = _a.sent();
                        return [2 /*return*/, res];
                }
            });
        });
    };
    Cls.prototype.request = function (_a) {
        var method = _a.method, path = _a.path, query = _a.query, data = _a.data;
        return __awaiter(this, void 0, void 0, function () {
            var options, baseHost, host, authorization, url, reqOption, _b, headers, body, statusCode, reqId, e_1, response, reqId;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0:
                        options = this.options;
                        baseHost = options.baseHost || 'cls.tencentcs.com';
                        host = options.region + "." + baseHost;
                        authorization = tencentSign({
                            secretId: options.secretId,
                            secretKey: options.secretKey,
                            // default 5 minutes
                            expire: options.expire || 300000,
                            method: method,
                            path: path,
                            parameters: query || {},
                            headers: {
                                Host: host,
                            },
                        });
                        url = "https://" + host + path;
                        reqOption = {
                            url: url,
                            method: method,
                            responseType: 'json',
                            headers: {
                                'Content-Type': 'application/json',
                                Authorization: authorization,
                                Host: host,
                            },
                            json: data || undefined,
                        };
                        if (query) {
                            reqOption.url = "https://" + host + path + "?" + querystring(query);
                        }
                        if (options.token) {
                            if (!reqOption.headers) {
                                reqOption.headers = {};
                            }
                            reqOption.headers['x-cls-token'] = options.token;
                        }
                        if (options.timeout) {
                            reqOption.timeout = options.timeout;
                        }
                        // debug request option
                        if (options.debug) {
                            logger('Request Option', JSON.stringify(reqOption));
                        }
                        _c.label = 1;
                    case 1:
                        _c.trys.push([1, 3, , 4]);
                        return [4 /*yield*/, got(reqOption)];
                    case 2:
                        _b = (_c.sent()), headers = _b.headers, body = _b.body, statusCode = _b.statusCode;
                        reqId = headers && headers['x-cls-requestid'];
                        if (!body) {
                            return [2 /*return*/, {
                                    requestId: reqId,
                                    success: statusCode === 200,
                                }];
                        }
                        body.requestId = reqId;
                        return [2 /*return*/, body];
                    case 3:
                        e_1 = _c.sent();
                        response = e_1.response || {};
                        reqId = response.headers && response.headers['x-cls-requestid'];
                        return [2 /*return*/, {
                                requestId: reqId,
                                error: {
                                    message: reqId ? e_1.message + " (reqId: " + reqId + ")" : e_1.message,
                                },
                            }];
                    case 4: return [2 /*return*/];
                }
            });
        });
    };
    return Cls;
}());

export { Cls, tencentSign };
//# sourceMappingURL=index.esm.js.map
