/**
 * IBizHttp net 对象
 * 调用 getInstance() 获取实例
 *
 * @class IBizHttp
 */
class IBizHttp {

    /**
     * 单例变量声明
     *
     * @static
     * @type {IBizHttp}
     * @memberof IBizHttp
     */
    public static iBizHttp: IBizHttp = null;

    /**
     * 是否正在加载中
     *
     * @type {boolean}
     * @memberof IBizHttp
     */
    public isLoading: boolean = false;

    /**
     * 统计加载
     *
     * @type {number}
     * @memberof IBizHttp
     */
    public loadingCount: number = 0;

    /**
     * Creates an instance of IBizHttp.
     * 私有构造，拒绝通过 new 创建对象
     * 
     * @memberof IBizHttp
     */
    public constructor() { }

    /**
     * 获取 IBizHttp 单例对象
     *
     * @static
     * @returns {IBizHttp}
     * @memberof IBizHttp
     */
    public static getInstance(): IBizHttp {
        if (!IBizHttp.iBizHttp) {
            IBizHttp.iBizHttp = new IBizHttp()
        }
        return this.iBizHttp
    }

    /**
     * post请求
     *
     * @param {string} url 请求路径
     * @param {*} [params={}] 请求参数
     * @returns {Subject<any>} 可订阅请求对象
     * @memberof IBizHttp
     */
    public post(url: string, params: any = {}): Subject<any> {
        let _this = this;
        const subject: Subject<any> = new rxjs.Subject();
        let win: any = window;
        let iBizApp: IBizApp = win.getIBizApp();
        if (!Object.is(iBizApp.getAppData(), '')) {
            Object.assign(params, { srfappdata: iBizApp.getAppData() });
        }
        const _strParams: string = _this.transformationOpt(params);
        const _url = url;
        _this.beginLoading();
        axios({
            baseURL: IBizEnvironment.Proxy,
            method: 'post',
            url: _url,
            data: _strParams,
            headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 'Accept': 'application/json' },
            transformResponse: [(data: any) => {
                let _data = null;
                try {
                    _data = JSON.parse(JSON.parse(JSON.stringify(data)));
                } catch (error) {

                }
                return _data;
            }],
        }).then((data: any) => {
            _this.endLoading();
            if (data && data.notlogin) {
                return;
            }
            if (data.ret !== 0) {
                data.failureType = 'CLIENT_INVALID';
                data.info = data.info ? data.info : '本地网络异常，请重试';
                data.info = data.errorMessage ? data.errorMessage : '本地网络异常，请重试';
            }
            IBizUtil.processResult(data);
            subject.next(data);
        }).catch((error: any) => {
            _this.endLoading();
            subject.error(error);
        });
        return subject;
    }

    /**
     * post请求,不处理loading加载
     *
     * @param {string} url
     * @param {*} [params={}]
     * @returns {Subject<any>}
     * @memberof IBizHttp
     */
    public post2(url: string, params: any = {}): Subject<any> {
        const subject: Subject<any> = new rxjs.Subject();
        let iBizApp: IBizApp = IBizApp.getInstance();

        if (!Object.is(iBizApp.getAppData(), '')) {
            Object.assign(params, { srfappdata: iBizApp.getAppData() });
        }
        const _strParams: string = this.transformationOpt(params);
        const _url = url;
        axios({
            baseURL: IBizEnvironment.Proxy,
            method: 'post',
            url: _url,
            data: _strParams,
            headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 'Accept': 'application/json' },
            transformResponse: [(data: any) => {
                let _data = null;
                try {
                    _data = JSON.parse(JSON.parse(JSON.stringify(data)));
                } catch (error) {

                }
                return _data;
            }],
        }).then((data: any) => {
            if (data && data.notlogin) {
                return;
            }
            if (data.ret !== 0) {
                data.failureType = 'CLIENT_INVALID';
                data.info = data.info ? data.info : '本地网络异常，请重试';
                data.info = data.errorMessage ? data.errorMessage : '本地网络异常，请重试';
            }
            IBizUtil.processResult(data);
            subject.next(data);
        }).catch((error: any) => {
            subject.error(error);
        });
        return subject;
    }

    /**
     * get请求
     *
     * @param {string} url 请求路径
     * @param {*} [params={}] 请求参数
     * @returns {Subject<any>} 可订阅请求对象
     * @memberof IBizHttp
     */
    public get(url: string, params: any = {}): Subject<any> {
        let _this = this;
        const subject: Subject<any> = new rxjs.Subject();
        let iBizApp: IBizApp = IBizApp.getInstance();

        if (!Object.is(iBizApp.getAppData(), '')) {
            Object.assign(params, { srfappdata: iBizApp.getAppData() });
        }
        if (Object.keys(params).length > 0) {
            const _strParams: string = _this.transformationOpt(params);
            url = url.indexOf('?') ? `${url}&${_strParams}` : `${url}?&${_strParams}`
        }

        const _url = url;
        _this.beginLoading();
        axios.get(_url, { baseURL: IBizEnvironment.Proxy, }).then(function (response) {
            _this.endLoading();
            subject.next(response);
        }).catch(function (error) {
            _this.endLoading();
            subject.error(error);
        });
        return subject;
    }

    /**
     * 请求参数转义处理
     *
     * @param {*} [opt={}]
     * @returns {string}
     * @memberof IBizHttp
     */
    public transformationOpt(opt: any = {}): string {
        let params: any = {};
        let postData: Array<string> = [];

        Object.assign(params, opt);
        let keys: string[] = Object.keys(params);
        keys.forEach((key: string) => {
            let val: any = params[key];
            if (val instanceof Array || val instanceof Object) {
                postData.push(`${key}=${encodeURIComponent(JSON.stringify(val))}`);
            } else {
                postData.push(`${key}=${encodeURIComponent(val)}`);
            }
        });
        return postData.join('&');
    }

    /**
     * 开始加载
     *
     * @memberof IBizHttp
     */
    public beginLoading(): void {
        if (this.loadingCount === 0) {
            setTimeout(() => {
                this.isLoading = true;
            });
        }
        this.loadingCount++;
    }

    /**
     * 加载结束
     *
     * @memberof IBizHttp
     */
    public endLoading(): void {
        if (this.loadingCount > 0) {
            this.loadingCount--;
        }
        setTimeout(() => {
            if (this.loadingCount === 0) {
                this.isLoading = false;
            }
        }, 500);
    }
}