import ResponseData from './response-data';
import URIUtil from './uri'
export default class FetchHelper {

    static request(url, opts, fetchParams) {

        opts = Object.assign(opts, fetchParams);
        opts.credentials || (opts.credentials = "include");

        return new Promise((resolve, reject) => {
            fetch(url, opts)
                .then(res => {
                    if (res.status === 401) {
                        window.location.href = `${process.env.PUBLIC_URL}/login`;
                        return;
                    }
                    resolve(res);
                })
                .catch(err => {
                    reject(err);
                });
        });
    }

    static requestJson(url, opts, fetchParams) {

        return new Promise((resolve, reject) => {

            this.request(url, opts, fetchParams)
                .then(res => {
                    res.json()
                        .then(data => {
                            if (data.code === 401) {
                                window.location.href = `${process.env.PUBLIC_URL}/login`;
                                return;
                            }
                            resolve(data);
                        })
                        .catch(err => {
                            reject(ResponseData.from(err));
                        });
                })
                .catch(err => {
                    if (err?.status === 401) {
                        window.location.href = `${process.env.PUBLIC_URL}/login`;
                        return;
                    }
                    if (!(err instanceof Response)) {
                        reject(ResponseData.from(err));
                        return;
                    }

                    err.json()
                        .then(data => {
                            reject(ResponseData.from(data));
                        })
                        .catch(() => {
                            reject(ResponseData.from(err));
                        });
                });
        });
    }

    static getJson(url, params, fetchParams) {
        url = URIUtil.appendParams(url, params)
        const opts = {
            method: 'GET',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
        }
        return this.requestJson(url, opts, fetchParams);
    }

    static postJson(url, body, fetchParams) {

        const opts = {
            method: 'POST',
            body: body && JSON.stringify(body),
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                'accept': '*/*',
            },
        }

        return this.requestJson(url, opts, fetchParams);
    }

    static putJson(url, body, fetchParams) {

        const opts = {
            method: 'PUT',
            body: body && JSON.stringify(body),
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
        }

        return this.requestJson(url, opts, fetchParams);
    }

    static deleteJson(url, body, fetchParams) {

        const opts = {
            method: 'DELETE',
            body: body && JSON.stringify(body),
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
        }

        return this.requestJson(url, opts, fetchParams);
    }

    static fetch(url, opts, fetchParams, responseHandler) {

        return new Promise((resolve, reject) => {

            this.request(url, opts, fetchParams)
                .then(res => {

                    if (!responseHandler) {
                        resolve(res);
                        return;
                    }

                    responseHandler(res)
                        .then(data => {
                            resolve(data);
                        })
                        .catch(err => {
                            reject(ResponseData.from(err));
                        });
                })
                .catch(err => {
                    if (!(err instanceof Response)) {
                        reject(ResponseData.from(err));
                        return;
                    }

                    err.json()
                        .then(data => {
                            reject(ResponseData.from(data));
                        })
                        .catch(() => {
                            reject(ResponseData.from(err));
                        });
                });
        });
    }

    static get(url, responseHandler, params, fetchParams) {
        url = URIUtil.appendParams(url, params)
        const opts = {
            method: 'GET',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
        }
        return this.fetch(url, opts, fetchParams, responseHandler);
    }

    static post(url, responseHandler, body, fetchParams) {

        const opts = {
            method: 'POST',
            body: body && JSON.stringify(body),
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                'accept': '*/*',
            },
        }

        return this.fetch(url, opts, fetchParams, responseHandler);
    }

    static put(url, responseHandler, body, fetchParams) {

        const opts = {
            method: 'PUT',
            body: body && JSON.stringify(body),
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
        }

        return this.fetch(url, opts, fetchParams, responseHandler);
    }

    static delete(url, responseHandler, body, fetchParams) {

        const opts = {
            method: 'DELETE',
            body: body && JSON.stringify(body),
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
        }

        return this.fetch(url, opts, fetchParams, responseHandler);
    }
}