/**
 * Created by PanJiaChen on 16/11/18.
 */
const sha1 = require("js-sha1");

/**
 * Parse the time to string
 * @param {(Object|string|number)} time
 * @param {string} cFormat
 * @returns {string | null}
 */
export function parseTime(time, cFormat) {
  if (arguments.length === 0 || !time) {
    return null;
  }
  const format = cFormat || "{y}-{m}-{d} {h}:{i}:{s}";
  let date;
  if (typeof time === "object") {
    date = time;
  } else {
    if (typeof time === "string") {
      if (/^[0-9]+$/.test(time)) {
        // support "1548221490638"
        time = parseInt(time);
      } else {
        // support safari
        // https://stackoverflow.com/questions/4310953/invalid-date-in-safari
        time = time.replace(new RegExp(/-/gm), "/");
      }
    }

    if (typeof time === "number" && time.toString().length === 10) {
      time = time * 1000;
    }
    date = new Date(time);
  }
  const formatObj = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay(),
  };
  const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
    const value = formatObj[key];
    // Note: getDay() returns 0 on Sunday
    if (key === "a") {
      return ["日", "一", "二", "三", "四", "五", "六"][value];
    }
    return value.toString().padStart(2, "0");
  });
  return time_str;
}

/**
 * @param {number} time
 * @param {string} option
 * @returns {string}
 */
export function formatTime(time, option) {
  if (("" + time).length === 10) {
    time = parseInt(time) * 1000;
  } else {
    time = +time;
  }
  const d = new Date(time);
  const now = Date.now();

  const diff = (now - d) / 1000;

  if (diff < 30) {
    return "刚刚";
  } else if (diff < 3600) {
    // less 1 hour
    return Math.ceil(diff / 60) + "分钟前";
  } else if (diff < 3600 * 24) {
    return Math.ceil(diff / 3600) + "小时前";
  } else if (diff < 3600 * 24 * 2) {
    return "1天前";
  }
  if (option) {
    return parseTime(time, option);
  } else {
    return (
      d.getMonth() +
      1 +
      "月" +
      d.getDate() +
      "日" +
      d.getHours() +
      "时" +
      d.getMinutes() +
      "分"
    );
  }
}

/**
 * @param {string} url
 * @returns {Object}
 */
export function getQueryObject(url) {
  url = url == null ? window.location.href : url;
  const search = url.substring(url.lastIndexOf("?") + 1);
  const obj = {};
  const reg = /([^?&=]+)=([^?&=]*)/g;
  search.replace(reg, (rs, $1, $2) => {
    const name = decodeURIComponent($1);
    let val = decodeURIComponent($2);
    val = String(val);
    obj[name] = val;
    return rs;
  });
  return obj;
}

/**
 * @param {string} input value
 * @returns {number} output value
 */
export function byteLength(str) {
  // returns the byte length of an utf8 string
  let s = str.length;
  for (var i = str.length - 1; i >= 0; i--) {
    const code = str.charCodeAt(i);
    if (code > 0x7f && code <= 0x7ff) s++;
    else if (code > 0x7ff && code <= 0xffff) s += 2;
    if (code >= 0xdc00 && code <= 0xdfff) i--;
  }
  return s;
}

/**
 * @param {Array} actual
 * @returns {Array}
 */
export function cleanArray(actual) {
  const newArray = [];
  for (let i = 0; i < actual.length; i++) {
    if (actual[i]) {
      newArray.push(actual[i]);
    }
  }
  return newArray;
}

/**
 * @param {Object} json
 * @returns {Array}
 */
export function param(json) {
  if (!json) return "";
  return cleanArray(
    Object.keys(json).map((key) => {
      if (json[key] === undefined) return "";
      return encodeURIComponent(key) + "=" + encodeURIComponent(json[key]);
    })
  ).join("&");
}

/**
 * @param {string} url
 * @returns {Object}
 */
export function param2Obj(url) {
  const search = url.split("?")[1];
  if (!search) {
    return {};
  }
  return JSON.parse(
    '{"' +
      decodeURIComponent(search)
        .replace(/"/g, '\\"')
        .replace(/&/g, '","')
        .replace(/=/g, '":"')
        .replace(/\+/g, " ") +
      '"}'
  );
}

/**
 * @param {string} val
 * @returns {string}
 */
export function html2Text(val) {
  const div = document.createElement("div");
  div.innerHTML = val;
  return div.textContent || div.innerText;
}

/**
 * Merges two objects, giving the last one precedence
 * @param {Object} target
 * @param {(Object|Array)} source
 * @returns {Object}
 */
export function objectMerge(target, source) {
  if (typeof target !== "object") {
    target = {};
  }
  if (Array.isArray(source)) {
    return source.slice();
  }
  Object.keys(source).forEach((property) => {
    const sourceProperty = source[property];
    if (typeof sourceProperty === "object") {
      target[property] = objectMerge(target[property], sourceProperty);
    } else {
      target[property] = sourceProperty;
    }
  });
  return target;
}

/**
 * Retrieves a value from an object based on a string
 * @param {object} data
 * @param {string} keyString
 */
export function objectFindLikeValue(data, keyString = "") {
  // console.log(arguments)
  if (!keyString.trim()) return data;
  const keyArr = keyString.split(".");
  let value = data;
  do {
    const key = keyArr.shift();
    const tempValue = value[key];
    if (!tempValue) {
      return tempValue;
    } else {
      value = tempValue;
    }
  } while (keyArr.length);
  return value;
}

/**
 * Expand the key of the object
 * @param {Object} obj
 * @param {Object} oldObj
 * @returns {Object}
 */
export function unfoldObjectKey(obj, oldObj = {}) {
  const allKeys = Object.keys(obj);
  const defaultObj = JSON.parse(JSON.stringify(oldObj));
  do {
    const itemKey = allKeys.shift();
    const itemKeyArr = itemKey.split(".");
    if (itemKeyArr.length > 1) {
      const key = itemKeyArr.shift();
      const objKey = itemKeyArr.join(".");
      defaultObj[key] = unfoldObjectKey(
        {
          [objKey]: obj[itemKey],
        },
        defaultObj[key]
      );
    } else {
      defaultObj[itemKey] = obj[itemKey];
    }
  } while (allKeys.length);
  return defaultObj;
}

/**
 * merge object value to array
 * @param {Object} obj
 * @param {Array} arr
 * @param {String} indexKey
 * @param {string} toKey
 * @returns {Array}
 */
export function mergeObjectValueToArray(obj, arr, indexKey, toKey) {
  return arr.map((item) => {
    const key = item[indexKey];
    item[toKey] = objectFindLikeValue(obj, key);
    return { ...item };
  });
}

/**
 * @param {HTMLElement} element
 * @param {string} className
 */
export function toggleClass(element, className) {
  if (!element || !className) {
    return;
  }
  let classString = element.className;
  const nameIndex = classString.indexOf(className);
  if (nameIndex === -1) {
    classString += "" + className;
  } else {
    classString =
      classString.substr(0, nameIndex) +
      classString.substr(nameIndex + className.length);
  }
  element.className = classString;
}

/**
 * @param {string} type
 * @returns {Date}
 */
export function getTime(type) {
  if (type === "start") {
    return new Date().getTime() - 3600 * 1000 * 24 * 90;
  } else {
    return new Date(new Date().toDateString());
  }
}

/**
 * @param {Function} func
 * @param {number} wait
 * @param {boolean} immediate
 * @return {*}
 */
export function debounce(func, wait, immediate) {
  let timeout, args, context, timestamp, result;

  const later = function () {
    // 据上一次触发时间间隔
    const last = +new Date() - timestamp;

    // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
    if (last < wait && last > 0) {
      timeout = setTimeout(later, wait - last);
    } else {
      timeout = null;
      // 如果设定为immediate===true，因为开始边界已经调用过了此处无需调用
      if (!immediate) {
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      }
    }
  };

  return function (...args) {
    context = this;
    timestamp = +new Date();
    const callNow = immediate && !timeout;
    // 如果延时不存在，重新设定延时
    if (!timeout) timeout = setTimeout(later, wait);
    if (callNow) {
      result = func.apply(context, args);
      context = args = null;
    }

    return result;
  };
}

export function getFileHash(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsArrayBuffer(file);
    reader.onload = function (ev) {
      try {
        const file = ev.target.result;
        const str = sha1(file);
        resolve(str);
      } catch (e) {
        reject(e);
      }
    };
  });
}

/**
 * This is just a simple version of deep copy
 * Has a lot of edge cases bug
 * If you want to use a perfect deep copy, use lodash's _.cloneDeep
 * @param {Object} source
 * @returns {Object}
 */
export function deepClone(source) {
  if (!source && typeof source !== "object") {
    throw new Error("error arguments", "deepClone");
  }
  const targetObj = source.constructor === Array ? [] : {};
  Object.keys(source).forEach((keys) => {
    if (source[keys] && typeof source[keys] === "object") {
      targetObj[keys] = deepClone(source[keys]);
    } else {
      targetObj[keys] = source[keys];
    }
  });
  return targetObj;
}

/**
 * @param {Array} arr
 * @returns {Array}
 */
export function uniqueArr(arr) {
  return Array.from(new Set(arr));
}

/**
 * @returns {string}
 */
export function createUniqueString() {
  const timestamp = +new Date() + "";
  const randomNum = parseInt((1 + Math.random()) * 65536) + "";
  return (+(randomNum + timestamp)).toString(32);
}

/**
 * Check if an element has a class
 * @param {HTMLElement} elm
 * @param {string} cls
 * @returns {boolean}
 */
export function hasClass(ele, cls) {
  return !!ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)"));
}

/**
 * Add class to element
 * @param {HTMLElement} elm
 * @param {string} cls
 */
export function addClass(ele, cls) {
  if (!hasClass(ele, cls)) ele.className += " " + cls;
}

/**
 * Remove class from element
 * @param {HTMLElement} elm
 * @param {string} cls
 */
export function removeClass(ele, cls) {
  if (hasClass(ele, cls)) {
    const reg = new RegExp("(\\s|^)" + cls + "(\\s|$)");
    ele.className = ele.className.replace(reg, " ");
  }
}

export function routerFormart(roles) {
  const pages = roles.filter((item) => item.parent !== null);
  const arr = [];
  pages.map((item) => {
    arr.push(item.parent.name);
  });
  const mapArr = [...new Set(arr)];

  var resources = [];
  for (let i = 0; i < mapArr.length; i++) {
    const r = pages.filter((item) => item.parent.name === mapArr[i]);
    const pArr = [];
    r.map((item) => {
      // console.log(item);
      const p = {
        id: item.permissionId,
        path: item.pages[0].route,
        name: item.pages[0].name,
        component: item.pages[0].route,
        icon: item.pages[0].icon,
        order: item.pages[0].index,
        hidden: item.hiden,
      };
      pArr.push(p);
    });
    const resource = {
      id: 1,
      path: r[0].parent.route,
      name: r[0].parent.name,
      component: "Layout",
      hidden: r.hiden,
      icon: r[0].parent.icon,
      order: r[0].parent.index,
      children: [...pArr],
      meta: {
        title: r[0].parent.name,
        icon: r[0].parent.icon,
      },
      alwaysShow: true,
    };
    resources.push(resource);
  }
  // resources.sort(compare('order'))
  return resources.sort(compare("order"));
}
function compare(p) {
  return function (m, n) {
    var a = m[p];
    var b = n[p];
    return a - b;
  };
}
export function fileNameFilter(val) {
  const reg = new RegExp(/\/.{32}:/);
  const str = reg.exec(val)[0];
  const vals = val.split(str);
  return vals[vals.length - 1];
}
export function errorCodeMap(code) {
  const errorCodeMap = {
    1001: "用户已存在",
    1003: "用户不存在",
    1004: "账号已存在",
    200004: "获取对象失败",
    200005: "访问数据异常",
    200006: "身份证格式异常",
    200101: "验证码错误",
    200102: "账号验证不通过",
    200103: "账号已被禁用",
    200010: "权限资源不存在",
    401: "未经授权",
    403: "无访问权限",
    404: "接口不存在",
    400001: "请求参数错误",
    400002: "服务器繁忙,请稍后重试",
    400006: "修改内容与任务当前阶段不匹配,请重试",
    400007: "任务已转交,无权处理",
    400008: "app绑定手机号与现在绑定手机号不一致",
    400009: "无审核修改权限",
    400010: "当前任务阶段无法审核",
    400102: "号码格式错误",
    403001: "TOKEN校验失败",
    403002: "刷新TOKEN校验失败",
    403003: "请登录后重试",
    500: "接口调用失败",
    670: "上架状态不能更新",
    671: "积分总数小于0",
    800: "稿件信息已经被审核",
    9000: "凭证过期",
    9997: "数据中有异常",
    9998: "数据已使用,请刷新数据",
    9999: "未知数据",
  };
  return errorCodeMap[code];
}

export const staffOptions = [
  { label: "在职", value: "1" },
  { label: "离职", value: "0" },
];

export const staffTypeOptions = [
  { label: "管理员", value: 0 },
  { label: "领导", value: 1 },
  { label: "拆迁办", value: 2 },
  { label: "街道办", value: 3 },
  { label: "开发商", value: 4 },
  { label: "银行", value: 5 },
  { label: "普通用户", value: 9 },
];

export const housingStatusOptions = [
  { label: "在售", value: "SALE" },
  { label: "已售", value: "SOLD" },
  { label: "下架", value: "OFF_SHELF" },
];
