/*
 * @Author: Rindy
 * @Date: 2019-08-06 16:25:08
 * @LastEditors: Rindy
 * @LastEditTime: 2020-07-29 17:36:36
 * @Description: Request
 */

import Vue from "vue";
import logger from "./logger";
import browser from "./browser";
import { base64ToBlob } from "./file";
import { checkLogin } from "@/api";
import { LoginDetector } from "@/utils/starter";
import { $alert, $confirm } from "@/components/shared/message";

let vue = new Vue();

// 空函数
const noop = function() {};
// 请求回调队列
let postQueue = [];

export const statusCode = {
  NEXT: -999, //继续执行
  SUCCESS: 0, //成功
  EXCEPTION: -1, //异常错误
  FAILURE_CODE_3002: 3002, //请至少保留一个场景。
  FAILURE_CODE_3003: 3003, //文件名称不允许超过50个字符
  FAILURE_CODE_3005: 3005, //不是该用户作品
  FAILURE_CODE_3006: 3006, //作品已被删除，无法编辑
  FAILURE_CODE_3007: 3007, //素材已被引用，无法删除。
  FAILURE_CODE_5003: 5003, //不支持此图片
  FAILURE_CODE_7005: 7005, //审核中不能编辑
  FAILURE_CODE_7006: 7006, //已审核不能编辑
  FAILURE_CODE_5001: 5001, //token失效
  FAILURE_CODE_5004: 5004, // 密码错误
};

/**
 * 已知错误提示集合
 */
// const defineErrorCode = []

let __showNetworkError = false;

const showLoginTips = () => {
  // 防止多次请求弹出
  if (showLoginTips.__is_show) {
    return;
  }

  showLoginTips.__is_show = true;

  return $confirm({
    title: "提示",
    content: "您没有登录，请登录后再编辑",
    okText: "去登录",
    noText: "登录完毕，继续",
    okLink: "/",
    ok: function() {
      showLoginTips.__is_show = false;
      return false;
    },
    no: function() {
      checkLogin().then((response) => {
        if (response.code === statusCode.SUCCESS) {
          postQueue.length && postQueue.forEach((item) => item());
          postQueue = [];
          LoginDetector.valid();
          let url = window.location.href
          window.location.href = url
        } else if (response.code === statusCode.FAILURE_CODE_5001) {
          showLoginTips();
        }
      });
      showLoginTips.__is_show = false;
    },
  });
};

function getCookie(objname) {
  //获取指定名称的cookie的值
  var arrstr = document.cookie.split("; ");
  for (var i = 0; i < arrstr.length; i++) {
    var temp = arrstr[i].split("=");
    if (temp[0] == objname) return unescape(temp[1]);
  }
}

export function getToken() {
  return (
    browser.urlHasValue("token", true) || localStorage.getItem("token") || getCookie("fdkankantoken") || ""
  );
}

export function statusCodesHandler(result, callback) {
  if (result.code == statusCode.FAILURE_CODE_7005) {
    return $alert({
      content: "该VR作品待审核，不可编辑。",
      forceOK: true,
      ok: () => {
        let url = window.location.href
        window.location.href = url
      },
    });
  }

  if (result.code == statusCode.FAILURE_CODE_7006) {
    return $alert({
      content: "该VR作品已审核，不可编辑。",
      forceOK: true,
      ok: () => {
        window.location.reload();
      },
    });
  }

  if (result.code == statusCode.FAILURE_CODE_3007) {
    return $alert({ content: "素材已被引用，无法删除。" });
  }

  if (result.code == statusCode.FAILURE_CODE_3002) {
    return $alert({ content: "请至少保留一个场景。" });
  }

  if (result.code == statusCode.FAILURE_CODE_3006) {
    return $alert({ content: "作品已被删除，无法编辑" });
  }

  if (result.code == statusCode.FAILURE_CODE_3005) {
    return;
  }

  if (result.code == statusCode.FAILURE_CODE_3003) {
    return statusCode.FILE;
    // return $alert({ content: '文件名称不允许超过50个字符' })
  }

  if (result.code == statusCode.FAILURE_CODE_5003) {
    return statusCode.FILE;
    // return $alert({ content: '不支持此图片' })
  }

  if (result.code == statusCode.FAILURE_CODE_5004) {
    return $alert({ content: "密码错误" });
  }

  if (result.code == statusCode.FAILURE_CODE_5001) {
    callback(result.code);
    return showLoginTips();
  }

  if (result.code != statusCode.SUCCESS) {
    return $alert({ content: `${result.msg}` });
  }
  return statusCode.NEXT;
}

$.ajaxSetup({
  headers: {},
  beforeSend: function(xhr) {
    const token = getToken();
    if (token) {
      xhr.setRequestHeader("token", token);
    }
  },
  error: function() {
    // 出错时默认的处理函数
    if (__showNetworkError) {
      return;
    }
    __showNetworkError = true;
    $alert({
      content: "网络异常，请稍后再试",
      forceOK: true,
      ok: () => {
        __showNetworkError = false;
      },
    });
    return;
  },
  success: function() {},
  complete: function(data) {
  },
});

export const http = {
  statusCode,
  __request(xhr, method, url, data, done, fail) {
    if (typeof done != "function") {
      done = noop;
    }
    if (typeof fail != "function") {
      fail = noop;
    }

    xhr.done((result) => {
      if (typeof result.code !== "undefined") { 
        const flag = statusCodesHandler(result, function(code) {
          // 需要登录的状态
          if (code == statusCode.FAILURE_CODE_5001) {
            postQueue.push(function() {
              http[method](url, data, done, fail);
            });
            // if (url.indexOf('isLogin') == -1) {
            //     postQueue.push(function() {
            //         http[method](url, data, done, fail)
            //     })
            // }
          }
        });

        if (!flag) {
          return;
        }

        if (flag === statusCode.FILE) { // 并没有这个值
          done(result);
        }

        if (flag === statusCode.NEXT) {
          done(result, result.code == 0);
        }
      } else {
        done(result);
      }
    });

    xhr.fail(fail);

    xhr.always(() => (xhr = null));

    return xhr;
  },
  /**
   * Get请求
   * @param {String} url 请求地址
   * @param {Object?} data 请求参数
   * @param {Function?} done 成功回调
   * @param {Function?} fail 失败回调
   */
  get(url, data = {}, done, fail) {
    if (/\.json/.test(url)) {
      // json文件格式自动调用getJson方法
      return this.getJson(url, data, done, fail);
    }
    return this.__request($.get(url, data), "get", url, data, done, fail);
  },
  /**
   * Get Blob请求
   * @param {String} url 请求地址
   * @param {Object?} data 请求参数
   * @param {Function?} done 成功回调
   * @param {Function?} fail 失败回调
   */
  getText(url, data = {}, done, fail) {
    return this.__request(
      $.ajax({
        url: url,
        dataType: "text",
      }),
      "getText",
      url,
      data,
      done,
      fail
    );
  },
  /**
   * GetJson请求 读取json文件数据
   * @param {String} url 请求地址
   * @param {Object?} data 请求参数
   * @param {Function?} done 成功回调
   * @param {Function?} fail 失败回调
   */
  getJson(url, data = {}, done, fail) {
    return this.__request($.getJSON(url, data), "get", url, data, done, fail);
  },
  /**
   * Get Blob请求
   * @param {String} url 请求地址
   * @param {Object?} data 请求参数
   * @param {Function?} done 成功回调
   * @param {Function?} fail 失败回调
   */
  getBlob(url, data = {}, done, fail) {
    return this.__request(
      $.ajax({
        url: url,
        dataType: "blob",
      }),
      "getBlob",
      url,
      data,
      done,
      fail
    );
  },
  /**
   * Get Arraybuffer请求
   * @param {String} url 请求地址
   * @param {Object?} data 请求参数
   * @param {Function?} done 成功回调
   * @param {Function?} fail 失败回调
   */
  getArraybuffer(url, data = {}, done, fail) {
    return this.__request(
      $.ajax({
        url: url,
        dataType: "arraybuffer",
      }),
      "getArraybuffer",
      url,
      data,
      done,
      fail
    );
  },
  /**
   * Post 请求
   * @param {String} url 请求地址
   * @param {Object?} data 请求参数
   * @param {Function?} done 成功回调
   * @param {Function?} fail 失败回调
   */
  post(url, data = {}, done, fail) {
    return this.__request($.post(url, data), "post", url, data, done, fail);
  },
  /**
   * PostJson 请求
   * @param {String} url 请求地址
   * @param {Object?} data 请求参数
   * @param {Function?} done 成功回调
   * @param {Function?} fail 失败回调
   */
  postJson(url, data = {}, done, fail) {
    return this.__request(
      $.ajax({
        type: "POST",
        url: url,
        contentType: "application/json",
        data: JSON.stringify(data),
      }),
      "postJson",
      url,
      data,
      done,
      fail
    );
  },
  /**
   * Post 表单 支持文件上传
   * @param {String} url 请求地址
   * @param {FormData?} formData 请求参数
   * @param {Function?} done 成功回调
   * @param {Function?} fail 失败回调
   */
  postForm(url, formData, done, fail, onProgress) {
    if (typeof onProgress === "function") {
      return this.__request(
        $.ajax({
          type: "POST",
          url: url,
          processData: false,
          contentType: false,
          data: formData,
          xhr: function() {
            const xhr = new XMLHttpRequest();
            xhr.upload.addEventListener("progress", function(e) {
              onProgress(e.loaded / e.total);
            });
            xhr.onabort = () => {
              console.log('xhr aborted.');
            }
            return xhr;
          },
          // 覆盖全局配置的失败回调。因为无论是上传子集失败还是用户取消了上传，都不需要弹窗。
          error: function() {
          },
        }),
        "postForm",
        url,
        formData,
        done,
        fail
      );
    } else {
      return this.__request(
        $.ajax({
          type: "POST",
          url: url,
          processData: false,
          contentType: false,
          data: formData,
        }),
        "postForm",
        url,
        formData,
        done,
        fail
      );
    }
  },
  /**
   * 加载图片
   * @param {String} url 请求地址
   * @param {Number?} retry 重试次数,默认为3
   */
  loadImage(url, retry = 3) {
    const def = $.Deferred();
    const img = new Image();

    const load = () => {
      logger.warn("Retrying load image: " + url);
      this.loadImage(url, retry - 1)
        .done(def.resolve.bind(def))
        .progress(def.notify.bind(def))
        .fail(def.reject.bind(def));
    };

    img.onerror = function() {
      retry > 0
        ? setTimeout(() => load(), 1e3)
        : def.reject(`[${url}]加载失败`);
    };

    img.onload = function() {
      def.resolve(img);
    };

    img.crossOrigin = "anonymous";
    img.src = url;

    return def;
  },
  /**
   * 上传文件
   * @param {String} url 请求地址
   * @param {Object?} data 请求参数
   * @param {Function?} done 成功回调
   * @param {Function?} fail 失败回调
   */
  uploadFile(url, data = {}, done, fail, onProgress) {
    const form = new FormData();
    // if (file.needTransfer) { //ie和苹果都不支持dataURLtoFile得传送,所以只能用blob
    //     form.append("file", common.dataURLtoBlob(file.file), file.name || file.file.name);
    // } else {
    //     form.append("file", file.file, file.name || file.file.name);
    // }
    for (let key in data) {
      if (key == "file") {
        form.append("file", data[key], data.filename || data[key].name);
      } else if (key != "filename") {
        form.append(key, data[key]);
      }
    }
    return this.postForm(url, form, done, fail, onProgress);
  },
  /**
   * 上传文件
   * @param {String} url 请求地址
   * @param {Object?} data 请求参数 {file:'base64 string',filename:'image.jpg',...}
   * @param {Function?} done 成功回调
   * @param {Function?} fail 失败回调
   */
  uploadBlobFile(url, data = {}, done, fail) {
    const form = new FormData();
    for (let key in data) {
      if (key === "file") {
        form.append("file", base64ToBlob(data.file), data.filename);
      } else if (key != "filename") {
        form.append(key, data[key]);
      }
    }
    return this.postForm(url, form, done, fail);
  },
};
