import assign from 'object-assign';
import ajax from './index';
import Cache from './cache';

class WebApi {
  constructor(ajaxUrl: string, dbParams: TspComponentAjaxCacheParams) {
    this.ajaxUrl = ajaxUrl;
    try {
      if ('open' in indexedDB) {
        this.isSupportIndexDB = true;
      }
    } catch (e) {
      this.isSupportIndexDB = false;
    }
    if (this.isSupportIndexDB && dbParams && dbParams.dbName && dbParams.tableName) {
      this.cache = new Cache(dbParams.dbName, dbParams.tableName);
      this.cache.open();
    }
  }

  /**
   * 成功后执行的响应函数
   */
  public static response: (result: any, callback: (params: any) => void, sendData: any) => void;
  /**
   * 响应成功后无论执行码是什么都要执行的函数
   */
  public static alwaysDone: () => void;
  /**
   * 默认请求参数
   */
  public static defaultParams: any;
  /**
   * 代理
   */
  public static proxy: string;
  /**
   * 已发送的请求
   */
  public static requested: XMLHttpRequest[] = [];
  /**
   * 取消请求
   */
  public static abort(noAbortUrl?: string[], abortUrl?: string[]): void {
    const length = WebApi.requested.length;
    const noAbortUrlLength = noAbortUrl ? noAbortUrl.length : 0;
    const abortUrlLength = abortUrl ? abortUrl.length : 0;
    let i;
    let j;
    if (abortUrlLength) {
      for (i = 0; i < length; i++) {
        if (WebApi.requested[i].readyState === 1) {
          for (j = 0; j < abortUrlLength; j++) {
            if (WebApi.requested[i]['url'] === abortUrl[j]) {
              WebApi.requested[i]['isAbort'] = true;
              WebApi.requested[i].abort();
              break;
            }
          }
        }
      }
    } else {
      for (i = 0; i < length; i++) {
        let flag = true;
        if (WebApi.requested[i].readyState === 1) {
          for (j = 0; j < noAbortUrlLength; j++) {
            if (WebApi.requested[i]['url'] !== noAbortUrl[j]) {
              flag = false;
              break;
            }
          }
          if (flag) {
            WebApi.requested[i]['isAbort'] = true;
            WebApi.requested[i].abort();
          }
        }
      }
    }
  }
  /**
   * 判断是否支持indexedDB
   */
  private isSupportIndexDB: boolean;
  /**
   * api请求基本地址
   */
  private ajaxUrl: string;
  /**
   * Cache 实例
   */
  private cache: Cache;

  /**
   * post请求
   */
  public post(options: TspComponentAjaxPostOption): void {
    // ajax需要的url
    let apiUrl;
    // request对象，用于执行abort
    let requested;
    // 从数据库读取的数据
    let cacheResult;
    // 判断api是否带有http
    if (options.api.indexOf('://') >= 0) {
      apiUrl = options.api;
    } else {
      apiUrl = WebApi.proxy ? WebApi.proxy + options.api : this.ajaxUrl + options.api;
    }

    const sendData =  WebApi.defaultParams ? assign({}, WebApi.defaultParams, options.params) : options.params;
    const xhrType = options.type ? options.type : 'POST';
    const apiInfo = {
      api: apiUrl,
      type: xhrType,
      params: sendData
    };
    const ajaxSendObj = {
      url: apiUrl,
      type: xhrType,
      contentType: options.contentType,
      customHeader: options.customHeader,
      timeout: options.timeout,
      data: sendData,
      success: (result, xhr) => {
        if (WebApi.response) {
          WebApi.response(result, (status) => {
            if (options.isCache && this.isSupportIndexDB) {
              if ((JSON.stringify(cacheResult.value) !== JSON.stringify(result)) && status) {
                const value = {
                  api: JSON.stringify({ url: apiUrl, params: options.params }),
                  value: result
                };
                const cacheUpdate = cacheResult.value ? true : false;
                options.success(result, status, cacheUpdate);
                if (cacheResult.value) {
                  this.cache.put(value);
                  // Toast.text('内容已更新');
                } else {
                  this.cache.add(value);
                }
              } else if (!cacheResult.value) {
                options.success(result, status);
              }
            } else {
              options.success(result, status);
            }
          }, JSON.stringify(assign({}, apiInfo, { result })));
        } else {
          console.error('缺少WebApi.response');
        }
        if (WebApi.alwaysDone) {
          WebApi.alwaysDone();
        }
      },
      error: (xhr) => {
        if (xhr['isAbort']) {
          return;
        }
        if (WebApi.alwaysDone) {
          WebApi.alwaysDone();
        }
        if (options.isCache && this.isSupportIndexDB) {
          if (options.timeoutCallback && !cacheResult.value) {
            options.timeoutCallback(xhr);
          }
        } else if (options.timeoutCallback) {
          options.timeoutCallback(xhr);
        }
      },
      complete(xhr: XMLHttpRequest): void {
        if (options.complete) {
          options.complete(xhr);
        }
      }
    };

    if (options.isCache && this.isSupportIndexDB) {
      this.cache.read({
        key: JSON.stringify({ url: apiUrl, params: options.params }),
        onsuccess(result: any): void {
          cacheResult = result;
          requested = ajax(ajaxSendObj);
          if (options.cacheReadSuccess) {
            options.cacheReadSuccess(result.value);
          }
          if (result.value) {
            WebApi.response(result.value, (params) => {
              options.success(result.value, params, false);
            }, JSON.stringify(assign({}, apiInfo, { result })));
          }
          WebApi.requested.push(requested);
        }
      });
    } else {
      requested = ajax(ajaxSendObj);
      WebApi.requested.push(requested);
    }
  }
}

export default WebApi;