import superagent from 'superagent';

export default class ReduxThunkRequest {
    _hashMap = {};
    _counterServerWaitedRequests = 0;
    _failedFlag = false;
    isWaited() {
        return this._counterServerWaitedRequests > 0;
    }
    constructor({baseUrl, defaultErrorHandler = (err, res) => {}, getAccessToken = () => {}} = {}) {
        this._baseUrl = baseUrl;
        this._defaultErrorHandler = defaultErrorHandler;
        this._getAccessToken = getAccessToken;
    }
    request(url, {method = 'get', accept = 'application/json', query, send, contentType, accessToken = this._getAccessToken(), attach, fields, serverWatch} = {}) {
        if((url.charAt(0) === '/') && this._baseUrl) {
            url = this._baseUrl + url;
        }
        const hashKey = url + JSON.stringify(accessToken) + method + JSON.stringify(query) + JSON.stringify(send);
        if(this._hashMap[hashKey]) {
            return this._hashMap[hashKey];
        }
        return new Promise((resolve, reject) => {
            let req;
            switch (method) {
                case 'get'    : req = superagent.get(url)  ; break;
                case 'post'   : req = superagent.post(url) ; break;
                case 'put'    : req = superagent.put(url)  ; break;
                case 'delete' : req = superagent.del(url)  ; break;
                default : throw {err:'Incorrect Method', res:{}}
            }
            if(accept) {
                req = req.set('Accept', accept);
            } else {
                req = req.set('Accept', 'application/json');
            }
            if(accessToken) {
                req = req.set('Authorization', 'Bearer ' + accessToken);
            }
            if(contentType) {
                req = req.set('Content-Type', contentType);
            }
            if(query) {
                req = req.query(query);
            }
            if(send) {
                req = req.send(send);
            }
            if(attach) {
                req = req.attach(...attach);
            }
            if(fields && Array.isArray(fields)) {
                for(let i = 0; i < fields.length; i++) {
                    req = req.field(...fields[i])
                }
            }
            if(serverWatch && !this._failedFlag) {
                this._counterServerWaitedRequests++;
            }
            req.end(
                (err, res) => {
                    delete this._hashMap[hashKey];
                    if(err) {
                        if(serverWatch) {
                            this._counterServerWaitedRequests = 0;
                            this._failedFlag = true;
                        }
                        this._defaultErrorHandler(err, res);
                        reject({err, res});
                    } else {
                        if(serverWatch) {
                            this._counterServerWaitedRequests--;
                        }
                        if(res.body !== undefined) {
                            resolve(res.body);
                        } else {
                            resolve(res.text);
                        }
                    }
                }
            );
        })
    }
}


