import utils from 'somes';
import { Request as RequestBase } from 'somes/request';
export class Request extends RequestBase {
    constructor(url, storage, signer) {
        super(url);
        this._storage = storage;
        if (signer)
            this.signer = signer;
    }
    parseResponseData(buf) {
        var json = buf.toString('utf8');
        var res = JSON.parse(json);
        if (res.code == 200) {
            return res.data;
        }
        else {
            res.errno = res.code;
            res.message = res.message || res.error || res.msg;
            throw Error.new(res);
        }
    }
    withoutErr(hold, fullname, useCacheAfterEetry = Infinity, interval = 5e3) {
        utils.assert(hold && typeof hold == 'object');
        var self = this;
        var handle = hold['__withoutErr_' + fullname];
        if (handle) {
            if (handle.cancel)
                handle.cancel();
        }
        else {
            hold['__withoutErr_' + fullname] = handle = {};
        }
        var name = fullname.split('#')[0];
        return function (params, options) {
            return new Promise(async function (resolve, reject) {
                var ok = false;
                var key = '_callApi_' + name + Object.hashCode(params);
                handle.cancel = function () {
                    if (!ok) {
                        ok = true;
                        reject(Error.new(`cancel request, ${name}`));
                    }
                };
                while (!ok) {
                    try {
                        var data = await self.request(name, options === null || options === void 0 ? void 0 : options.method, params, options);
                        if (!ok) {
                            if (useCacheAfterEetry !== Infinity) {
                                self._storage.set(key, data);
                            }
                            ok = true;
                            resolve(data);
                        }
                        break;
                    }
                    catch (err) {
                        if (ok) {
                            break;
                        }
                        else if (useCacheAfterEetry === 0) {
                            data = self._storage.get(key);
                            if (data) {
                                data.cached = true;
                                ok = true;
                                resolve(data);
                                break;
                            }
                        }
                        console.warn(err);
                    }
                    if (useCacheAfterEetry) {
                        useCacheAfterEetry--;
                    }
                    await utils.sleep(interval);
                }
            });
        };
    }
    async useCacheAfterErr(name, params, options) {
        var data;
        var key = '_callApi_' + name + Object.hashCode(params);
        try {
            data = await this.request(name, options === null || options === void 0 ? void 0 : options.method, params, options);
            this._storage.set(key, data);
        }
        catch (err) {
            data = this._storage.get(key);
            if (!data)
                throw err;
            data.cached = true;
        }
        return data;
    }
}
