import moment from 'moment';
import Reg from '../constants/validate';
import * as Pictures from '../pictures';
import qs from 'qs';

const dateFrom = 'YYYY/MM/DD';
export const dateFormatter = {
  YYYYMMDDHM: 'YYYY-MM-DD HH:mm',
};

export const formDateText = value => {
  if (value) {
    value = value < 0 ? 0 : value;
    let day = parseInt(value / 1000 / 60 / 60 / 24);
    let hour = parseInt((value / 1000 / 60 / 60) % 24);
    let minutes = parseInt((value / 1000 / 60) % 60);
    let seconds = parseInt((value / 1000) % 60);
    if (seconds > 0) {
      minutes += 1;
    }
    return `${day > 0 ? `${day} 天` : ''} ${hour > 9 ? hour : `0${hour}`} 小时 ${
      minutes > 9 ? minutes : `0${minutes}`
    } 分`;
  }
  return '';
};

export const formDate = (value, type = dateFrom) => {
  if (value) {
    return moment(value * 1000).format(type);
  }
  return '';
};

export const percentageStay = (value, all, id, fn) => {
  if (value) {
    return (value / all).toFixed(2) * 100 > 100 ? 0 : (value / all).toFixed(2) * 100;
  }
  fn && fn(id);
  return 0;
};
export const dateFormatToMoment = (timestamp, format = dateFrom) => {
  return moment(new Date(timestamp * 1000), format);
};

export const dateFormatToString = (timestamp, format = dateFrom) => {
  return moment(new Date(timestamp * 1000)).format(format);
};

export const dateFormatToTimestamp = (date, format = dateFrom) => {
  if (!date) return null;
  return parseInt(moment(date).valueOf() / 1000);
};
//获取两个时间戳的时间差值
// unit:years,months,minutes,seconds
// new Date 是 13 位的时间戳,使用的时候注意targetTimestamp,是否一致
export const dateDiffTimestamp = (currTimestamp, targetTimestamp, unit = 'days') => {
  currTimestamp = currTimestamp ? currTimestamp : new Date();
  return moment(currTimestamp).diff(moment(targetTimestamp), unit);
};
//获取两个时间冲的差值,单位为天,不按照小时计算
export const dateDiffTimestampByDay = (currTimestamp, targetTimestamp) => {
  currTimestamp = currTimestamp ? currTimestamp : new Date();
  return moment(moment(currTimestamp).format(dateFrom)).diff(
    moment(targetTimestamp * 1000).format(dateFrom),
    'days'
  );
};
export const setSessionStorageItem = (key, val) => {
  sessionStorage.setItem(key, JSON.stringify(val));
};

export const removeSessionStorageItem = (key, val) => {
  sessionStorage.removeItem(key);
};

export const getSessionStorageItem = key => {
  const value = sessionStorage.getItem(key);
  if (value) {
    return JSON.parse(value);
  }
  return null;
};

export const setLocalStorageItem = (key, val) => {
  localStorage.setItem(key, JSON.stringify(val));
};

export const getLocalStorageItem = key => {
  const value = localStorage.getItem(key);
  if (value) {
    return JSON.parse(value);
  }
  return null;
};

// Format money into thousandth format
export const moneyFormat = (val, needDigital = false) => {
  if (!val && val !== 0) return '';
  val = (val + '').replace(Reg.number1, ',');
  if (needDigital && !val.includes('.')) {
    return val + '.00';
  }
  return val;
};

export const trimSpace = val => {
  if (!val || typeof val !== 'string') return val;
  return val.trim();
};

// InputNumber 输入框格式化方法
export const inputNumberMoneyFormatter = value => (value ? '¥' + moneyFormat(value) : '');

// Limit only 0~9 and . can be input
export const parseNumber = value => {
  if (!value && value !== 0) return;
  return value.replace(Reg.nonNumber, '');
};

// Limit only number can be input
export const parseInterge = value => {
  if (!value && value !== 0) return;
  return value.toString().replace(Reg.nonInteger, '');
};

export const formatMoney = (number, places, symbol, thousand, decimal) => {
  number = number || 0;
  places = !isNaN((places = Math.abs(places))) ? places : 2;
  symbol = symbol || '¥';
  thousand = thousand || ',';
  decimal = decimal || '.';

  var negative = number < 0 ? '-' : '',
    i = parseInt((number = Math.abs(+number || 0).toFixed(places)), 10) + '',
    // eslint-disable-next-line
    j = (j = i.length) > 3 ? j % 3 : 0;
  return (
    symbol +
    negative +
    (j ? i.substr(0, j) + thousand : '') +
    i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + thousand) +
    (places ?
      decimal +
      Math.abs(number - i)
      .toFixed(places)
      .slice(2) :
      '')
  );
};

/**
 * 在contructor函数调用 bindMethods(this), 会自动绑定组件以on和handle开头的函数
 * @param {*} comInstance 组件实例
 * @param {*} comClass 组件类
 */
export function bindMethods(comInstance, comClass) {
  const prototype = comClass ? comClass.prototype : comInstance.constructor.prototype;
  Reflect.ownKeys(prototype).forEach(key => {
    if (key.startsWith('on') || key.startsWith('handle')) {
      comInstance[key] = comInstance[key].bind(comInstance);
    }
  });
}

/**
 * 剔除参数中的null、undefine、NaN等
 * @param {*} params 参数
 */
export function getVaildParams(params) {
  let newParams = {};
  Object.entries(params).forEach(([key, value]) => {
    if (![null, undefined, NaN].includes(value)) {
      newParams[key] = value;
    }
  });
  return newParams;
}

/**
 * 将对象中的null值改为undefine
 * @param {*} obj
 */
export function replaceNullValue(obj) {
  if (typeof obj !== 'object') {
    return;
  }
  // 数组
  if (Array.isArray(obj)) {
    obj.forEach(value => {
      replaceNullValue(value);
    });
    return;
  }

  // 对象
  Object.entries(obj).forEach(([key, value]) => {
    if (value === null) {
      obj[key] = undefined;
    } else {
      replaceNullValue(value);
    }
  });
}

/**
 * 对象数组根据指定属性去重
 * @param {array} 源数组
 * @param {key} 属性名
 * @returns 去重后的数组
 */
export const uniqueArray = (array, key) => {
  let result = [];
  let obj = {};
  if (!array || array.length === 0 || !array[0].hasOwnProperty(key)) return [];
  array.forEach(a => {
    if (!obj[a[key]]) {
      result.push(a);
      obj[a[key]] = true;
    }
  });
  return result;
};

/**
 * 浮点数转百位数
 * @param {var} 浮点数
 * @param {places} 小数位数
 * @returns 转换后的百位数
 */
export const floatToPercent = (val, places = 0) => {
  if (!val) {
    return val;
  }
  return (val * 100).toFixed(places);
};
/**
 * sort object desc based on its props
 * @param {prop} property name
 * @returns result
 */
export const compare = (prop, desc = 1) => {
  return (obj1, obj2) => {
    var val1 = obj1[prop];
    var val2 = obj2[prop];
    return !desc ? val1 - val2 : val2 - val1;
  };
};
/**
 * 数字转换
 * @param {var} 原始数据
 */
export const formatNumber = (val, range = 1, places = 0) => {
  if (!val) {
    return val;
  }
  return Number((val * range).toFixed(places));
};

// 数字字符串 去重排序 '0,1,2,2,2,3,2,,,1' to '0,1,2,3'
export const formatRangeNumber = str => {
  return Array.from(new Set(str.split(',').filter(item => item)))
    .map(item => parseInt(item))
    .sort((a, b) => a - b)
    .join(',');
};

//将base64转换为文件
export const convertBase64URLtoFile = (urlData, filename) => {
  const arr = urlData.split(',');
  const mime = arr[0].match(/:(.*?);/)[1];
  const bytes = window.atob(arr[1]);
  var buffer = new ArrayBuffer(bytes.length);
  var u8arr = new Uint8Array(buffer);

  for (let i = 0, length = bytes.length; i < length; i++) {
    u8arr[i] = bytes.charCodeAt(i);
  }
  return new File([u8arr], filename, {
    type: mime,
  });
};

export const checkLong = val => {
  // eslint-disable-next-line
  var longrg = /^(\-|\+)?(((\d|[1-9]\d|1[0-7]\d|0{1,3})\.\d{0,6})|(\d|[1-9]\d|1[0-7]\d|0{1,3})|180\.0{0,6}|180)$/;
  if (!longrg.test(val)) {
    return '经度整数部分为0-180,小数部分为0到6位!';
  }
  return true;
};

export const checkLat = val => {
  // eslint-disable-next-line
  var latreg = /^(\-|\+)?([0-8]?\d{1}\.\d{0,6}|90\.0{0,6}|[0-8]?\d{1}|90)$/;
  if (!latreg.test(val)) {
    return '纬度整数部分为0-90,小数部分为0到6位!';
  }
  return true;
};

export const isPc = (userAgentStr = navigator.userAgent) =>
  userAgentStr.match(
    /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
  ) ?
  false :
  true;

export function checkDataType(target) {
  const typeList = {
    '[object Array]': 'array',
    '[object Object]': 'object',
    '[object Number]': 'number-object',
    '[object Boolean]': 'Boolean-object',
    '[object String]': 'string-object',
  };
  if (target == null) {
    return 'null';
  }
  if (typeof target === 'object') {
    let type = Object.prototype.toString.call(target);
    return typeList[type];
  } else {
    return typeof target;
  }
}

export function isEmpty(obj) {
  let empty = false;

  switch (checkDataType(obj)) {
    case 'object':
      empty = !Boolean(Object.keys(obj).length);
      break;
    case 'array':
      empty = !Boolean(obj.length);
      break;
    case 'null':
      empty = true;
      break;
    default:
      break;
  }
  return empty;
}

/**
 * 检查两个数字或者字符串数组是否有交集
 * @param {*} arr1
 * @param {*} arr2
 */
export function isIntersection(arr1, arr2) {
  const len = arr1.length + arr2.length;
  return len > new Set([...arr1, ...arr2]).size;
}

/**
 * 数值保留位数
 * @param {number, string} value
 * @param {number} count 保留几位
 * @param {boolean} round 是否四舍五入
 */
export const saveDecimal = (value, count = 2, round = false) => {
  let newValue = parseFloat(value);
  if (!newValue) return 0; // 不是数字
  const fn = round ? Math.round : Math.floor;
  if (count === 0) return fn(newValue);
  const tens = Math.pow(10, count);
  return fn(newValue * tens) / tens;
};

/**
 * format range picker value
 * @param {*} validFrom eg: 1594964693
 * @param {*} validTo eg: 1594964693
 */
export const formatRangePickerValue = (validFrom, validTo) => [moment(validFrom), moment(validTo)];

// 费率转利率
export function interest2Rate(nper, pmt, pv, fv, type, guess) {
  // Sets default values for missing parameters
  fv = typeof fv !== 'undefined' ? fv : 0;
  type = typeof type !== 'undefined' ? type : 0;
  guess = typeof guess !== 'undefined' ? guess : 0.1;

  // Sets the limits for possible guesses to any
  // number between 0% and 100%
  var lowLimit = 0;
  var highLimit = 1;

  // Defines a tolerance of up to +/- 0.00005% of pmt, to accept
  // the solution as valid.
  var tolerance = Math.abs(0.00000005 * pmt);

  // Tries at most 40 times to find a solution within the tolerance.
  for (var i = 0; i < 40; i++) {
    // Resets the balance to the original pv.
    var balance = pv;

    // Calculates the balance at the end of the loan, based
    // on loan conditions.
    for (var j = 0; j < nper; j++) {
      if (type === 0) {
        // Interests applied before payment
        balance = balance * (1 + guess) + pmt;
      } else {
        // Payments applied before insterests
        balance = (balance + pmt) * (1 + guess);
      }
    }

    // Returns the guess if balance is within tolerance.  If not, adjusts
    // the limits and starts with a new guess.
    if (Math.abs(balance + fv) < tolerance) {
      return guess;
    } else if (balance + fv > 0) {
      // Sets a new highLimit knowing that
      // the current guess was too big.
      highLimit = guess;
    } else {
      // Sets a new lowLimit knowing that
      // the current guess was too small.
      lowLimit = guess;
    }

    // Calculates the new guess.
    guess = (highLimit + lowLimit) / 2;
  }

  // Returns null if no acceptable result was found after 40 tries.
  return null;
}
/**
 * 获取对象的深层属性,不存在返回undefine
 * getDeepProp({ a: { b: { c: 1 } } }, 'a.b')
 * @param {* object} obj
 * @param {* string} propStr
 */
export function getDeepProp(obj, propStr) {
  if (!obj) return undefined;
  if (!propStr) return obj;
  const props = propStr.split('.');
  return getDeepProp(obj[props[0]], props.slice(1).join('.'));
}

//手机号检验
export const checkPhone = function (phone) {
  if (!/^1[3456789]\d{9}$/.test(phone)) {
    return false;
  } else {
    return true;
  }
};
//邮箱校验
export const checkEmail = function (email) {
  if (!/^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/.test(email)) {
    return false;
  } else {
    return true;
  }
};
export const deepClone = obj => {
  if (!Object.prototype.toString.call(obj) === '[object Object]') {
    return obj;
  }
  return JSON.parse(JSON.stringify(obj));
};
export const sleep = ms => {
  return new Promise(resolve => setTimeout(resolve, ms));
};


// 获取搜索栏搜索参数
export const getSearchParams = () => {
  return qs.parse(window.location.search.slice(1)) || {};
};

//身份证截取(YYYY-MM-DD)
export const getBirthdatByIdNo = iIdNo => {
  let tmpStr = '';

  iIdNo = iIdNo.replace(/^\s+|\s+$/g, '');

  if (iIdNo.length == 15) {
    tmpStr = iIdNo.substring(6, 12);
    tmpStr = '19' + tmpStr;
    tmpStr = tmpStr.substring(0, 4) + '-' + tmpStr.substring(4, 6) + '-' + tmpStr.substring(6);
    return tmpStr;
  } else {
    tmpStr = iIdNo.substring(6, 14);
    tmpStr = tmpStr.substring(0, 4) + '-' + tmpStr.substring(4, 6) + '-' + tmpStr.substring(6);
    return tmpStr;
  }
};
//计算年龄(YYYY-MM-DD推出年龄)
export const getAge = strAge => {
  let birArr = strAge.split('-');
  let birYear = birArr[0];
  let birMonth = birArr[1];
  let birDay = birArr[2];

  d = new Date();
  let nowMonth = d.getMonth() + 1; //记得加1
  let nowYear = d.getFullYear();
  let nowDay = d.getDate();
  let returnAge;

  if (birArr == null) {
    return false;
  }
  let d = new Date(birYear, birMonth - 1, birDay);
  if (d.getFullYear() == birYear && d.getMonth() + 1 == birMonth && d.getDate() == birDay) {
    if (nowYear == birYear) {
      returnAge = 0; 
    } else {
      let ageDiff = nowYear - birYear; 
      if (ageDiff > 0) {
        if (nowMonth == birMonth) {
          let dayDiff = nowDay - birDay; 
          if (dayDiff < 0) {
            returnAge = ageDiff - 1;
          } else {
            returnAge = ageDiff;
          }
        } else {
          let monthDiff = nowMonth - birMonth; 
          if (monthDiff < 0) {
            returnAge = ageDiff - 1;
          } else {
            returnAge = ageDiff;
          }
        }
      }
    }
    return returnAge;
  }
};