
export const client = (function () {
  const hosts = 'http://192.168.200.129:6604/',
    uploaderUrl = 'http://192.168.200.129:6604/api/upload',
    loginPath = 'oauth',
    serverId = 0,
    clientVersion = '';

  let pool: any[] = [];
  let waite: any[] = [];
  let isLogin = false;

  const clearQueue = () => {
    pool = [];
    waite = [];
  };

  const requestApi = (url: string, method: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT', data: any, resolve: (res: any) => void, subject: (res: any) => void, retryOn401 = true) => {
    wx.request({
      url: hosts + url,
      header: {
        'AppId': serverId,
        'x-token': wx.getStorageSync('access_token'),
        'Content-Type': 'application/x-www-form-urlencoded',
        'Scene': wx.getStorageSync('scene'),
        'Version': clientVersion
      },
      method: method,
      data: data,
      dataType: 'json',
      success(token) {
        if (+token.statusCode === 401) {
          console.log(token, retryOn401);
          if (retryOn401) {
            make(url, method, data, resolve, subject);
          } else {
            subject(token);
          }
          return;
        }

        if (+token.statusCode === 200) {
          resolve(token.data);
          return;
        }

        subject(token);
      },
      fail(fai) {
        subject(fai);
      }
    });
  };

  const flushQueue = () => {
    const pending = pool.slice();
    clearQueue();

    console.log(pending);

    pending.forEach((item) => {
      request(item.url, item.method, item.data).then((data) => {
        item.resolve(data);
      }).catch((err) => {
        item.subject(err);
      });
    });
  };

  const rejectQueue = (error: any) => {
    const pending = pool.slice();
    console.log(pending);
    clearQueue();
    pending.forEach((item) => {
      item.subject(error);
    });
  };

  const login = () => {
    return new Promise((resolve, reject) => {
      if (isLogin === true) {
        return;
      }
      isLogin = true;

      const success = (value: any) => {
        if (value.code != 0) {
          rejectQueue(value);
          reject(value);

          wx.showModal({
            title: '温馨提示',
            content: '登录失败，请稍后再试',
            showCancel: false
          });
          return
        }
        wx.setStorageSync('access_token', value.data.token);
        setTimeout(() => {
          flushQueue();
          resolve(value);
        }, 50);
      };

      const fail = (err: any) => {
        rejectQueue(err);
        reject(err);
      };

      wx.login({
        timeout: 3000,
        success: (res) => {
          isLogin = false;
          const options = wx.getLaunchOptionsSync();
          requestApi(
            loginPath,
            'POST',
            {
              code: res.code,
              query: JSON.stringify(options.query),
              scene: options.scene
            },
            success,
            fail,
            false
          );
        },
        fail: (res) => {
          isLogin = false;
          rejectQueue(res);
          reject(res);
        }
      });
      // #endif
    });
  };

  const make = (url: string, method: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT', data: any, resolve: (res: any) => void, subject: (res: any) => void) => {
    const obj = {
      url: url,
      method: method,
      data: data,
      resolve: resolve,
      subject: subject
    };
    const key = method + url;
    if (waite.indexOf(key) === -1) {
      waite.push(key);
      pool.push(obj);
    }
    login().catch((res: any) => {
      console.log('catch', res);
      rejectQueue(res);
      subject(res);
    }).then((res: any) => {
      console.log('then', res);
    });
  };

  const request = (url: string, method: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT', data = {}) => {
    return new Promise((resolve, subject) => {
      const token = wx.getStorageSync('access_token');
      if (token !== null && token !== '') {
        requestApi(url, method, data, resolve, subject);
      } else {
        make(url, method, data, resolve, subject);
      }
    });
  };

  const upload = (imageUrl: string, data: any, path: string = '/api/upload/default') => {
    return new Promise((sCall, eCall) => {
      wx.uploadFile({
        filePath: imageUrl,
        name: 'file',
        url: 'http://192.168.200.129:6604' + path,
        header: {
          AppId: serverId,
          'x-token': wx.getStorageSync('access_token'),
          Version: clientVersion
        },
        formData: data,
        success(token) {
          try {
            const json = JSON.parse(token.data);
            if (token.statusCode === 401) {
              eCall(json);
            } else {
              sCall(json);
            }
          } catch (e) {
            eCall(e);
          }
        },
        fail(res) {
          wx.showModal({
            title: '错误提示',
            content: '网络异常，请稍后再试',
            showCancel: false
          });
          eCall(res);
        }
      });
    });
  };

  return {
    request,
    upload
  };
})()