import axios, {AxiosResponse, AxiosRequestConfig, AxiosInstance} from 'axios';
import {host, params, http} from '@/config';
import router from '@/router';
import Utils from '@/extend/Utils';
import {Loading} from 'element-ui';

export default class HttpRequest {

    public static getInstance(...args: any[]): any {
        let Class: any = this;
        if (!Class._instance) {
            let argsLen: number = args.length;
            if (argsLen === 0) {
                Class._instance = new Class();
            } else {
                Class._instance = new Class(...args);
            }
        }
        return Class._instance;
    }

    public loadingInstance: any;

    public queue: any; // 请求的url集合
    public redirect: number;
    public status: number;

    public constructor() {
        this.queue = {};
        this.redirect = 0;
        this.status = 0;
    }

    public async request(options: AxiosRequestConfig) {
        let opts = this.getOpts(options);
        const instance = axios.create();
        await this.interceptors(instance, opts);
        return instance(opts);
    }

    private interceptors(instance: any, options: AxiosRequestConfig) {
        // 请求拦截
        instance.interceptors.request.use((config: AxiosRequestConfig) => {
            // 添加全局的loading...
            // this.loadingInstance = Loading.service({
            //     lock: true,
            //     text: 'Loading',
            //     spinner: 'el-icon-loading',
            //     background: 'rgba(0, 0, 0, 0.7)',
            //     fullscreen: false
            // });
            if (!Object.keys(this.queue).length) {
                // show loading
            }
            if (options && options.url) {
                this.queue[options.url] = true;
            }
            return config;
        }, (error: any) => {
            console.log(error);
        });
        // 响应拦截
        instance.interceptors.response.use((res: AxiosResponse) => {
            // this.loadingInstance.close();
            if (options && options.url) {
                this.complete(options.url);
            }
            const {data, status} = res;
            if (status === 200 && data && data.code === 1) {
                return data;
            } // 请求成功
            this.redirect = 0;
            return this.fail(res, options); // 失败回调
        }, (error: any) => {
            if (options && options.url) {
                this.complete(options.url);
            }
            console.log(error);
        });
    }

    private getOpts(options: AxiosRequestConfig): AxiosRequestConfig {
        let opts: any = {
            method: 'GET', timeout: 5000, headers: {
                'content-type': 'application/json', // 默认值
                'Authorization': this.getToken('access_token'),
            }, baseURL: host
        };
        opts = Object.assign(opts, options);
        if (opts.method !== 'GET') {
            Object.assign(opts, {data: opts.data});
        } else {
            Object.assign(opts, {params: opts.data});
        }
        return opts;
    }

    private getToken(name: string) {
        let token = localStorage.getItem(name);
        // console.log(token);
        if (token) {
            return token;
        } else {
            return '';
        }
    }

    private clearToken() {
        localStorage.removeItem('access_token');
        localStorage.removeItem('refresh_token');
    }

    private async getAcessToken() {
        let res = await this.request({
            url: http.accesstoken, method: 'GET', data: {refresh_token: this.getToken('refresh_token')}, baseURL: host,
        });
        // @ts-ignore
        console.log(res);
        localStorage.setItem('access_token', res.data.access_token);
    }

    private async fail(res: AxiosResponse, options: AxiosRequestConfig) {
        let errStr = '网络繁忙！';

        if (this.redirect > 3) {
            return '网络繁忙';
        }

        switch (res.data.code.toString()) {
            case '20002':
            case '20003':
            case '20004':
            case '20005':
                console.info(res.data.msg);
                await this.getAcessToken();
                this.redirect++;
                delete options.headers;
                return this.request(options);
            case '20001':
            case '20006':
                this.clearToken();
                console.log('需要登录');
                return router.replace({name: 'login'});
            default:
                return {
                    err: console.error({
                        code: res.data.errcode || res.data.code, msg: res.data.errmsg || errStr
                    })
                };
        }
    }

    private complete(url: string) {
        delete this.queue[url];
        if (!Object.keys(this.queue).length) {
            // hide loading
        }
    }
}
