import store from '@/store'
import moment from 'moment'
import CryptoJS from 'crypto-js'
// import timemachine from 'timemachine'
const log = require('electron-log')
const si = require('systeminformation')
const Store = require('electron-store')

export const localStore = new Store()

export const cloneDeep = (obj, hash = new WeakMap()) => {
  //  if (typeof obj == "undefined" ) return obj;
  // 校验null/ undefined不能用上述方法
  if (obj == null) return obj
  if (typeof obj !== 'object') return obj
  if (obj instanceof Date) return new Date(obj)
  if (obj instanceof RegExp) return new RegExp(obj)

  // []/ {}   cloneObj
  let val = hash.get(obj)
  if (val) { // 映射表 存在  直接将结果返回  避免重复地址
    return val // 递归的终止条件
  }

  // 获取传入对象/方法的构造函数
  let cloneObj = new obj.constructor()

  for (let key in obj) {
    // 添加对象/ 数组 的自由属性，继承属性过滤
    if (obj.hasOwnProperty(key)) {
      cloneObj[key] = cloneDeep(obj[key], hash)
      hash.set(obj, cloneObj)
    }
  }
  return cloneObj
}

export const getIp = () => {
  let target = null

  return new Promise((resolve, reject) => {
    si.networkInterfaces(data => {
      const networkList = data.filter(i => {
        // 返回所有非虚拟和非内部的网络端口
        return !i.virtual && !i.internal
      })

      if (networkList.length === 0) {
        setTimeout(() => {
          resolve(getIp())
        }, 2000)
        return
      }

      if (networkList.length === 1) {
        target = networkList[0]
      } else {
        target = networkList.find(i => i.type === 'wired') || networkList[0]
      }

      target.link_type = target.type === 'wired' ? 'Ethernet' : 'WiFi'

      const { ip4: ip, mac, link_type } = target
      store.commit('SET_SELLER_DEVICE', { ip4: ip, mac, link_type })
      resolve({ ip, mac, link_type })
    })
  })
}

export function parseTime (time, cFormat) {
  if (arguments.length === 0) {
    return null
  }
  const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
  let date
  if (typeof time === 'object') {
    date = time
  } else {
    if (('' + time).length === 10) time = parseInt(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 timeStr = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
    let value = formatObj[key]
    if (key === 'a') return ['一', '二', '三', '四', '五', '六', '日'][value - 1]
    if (result.length > 0 && value < 10) {
      value = '0' + value
    }
    return value || 0
  })
  return timeStr
}

export function formatTime (time, option) {
  time = +time * 1000
  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() + '分'
  }
}

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

export function isUrl (url) {
  let reg = /^((https|http|ftp|rtsp|mms):\/\/)(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?(([0-9]{1,3}.){3}[0-9]{1,3}|([0-9a-z_!~*'()-]+.)*([0-9a-z][0-9a-z-]{0,61})?[0-9a-z].[a-z]{2,6})(:[0-9]{1,5})?((\/?)|(\/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+\/?)$/

  return reg.test(url)
}

// 设置表格总计行高亮
export function totalRowClassName ({ row, rowIndex }) {
  for (let key in row) {
    if (row[key] === '总计') {
      return 'table-total-row'
    }
    if ((row[key] + '').indexOf('售票员小计') > -1) {
      return 'table-total-row table-total-row1'
    }
    if ((row[key] + '').indexOf('售票点小计') > -1) {
      return 'table-total-row table-total-row2'
    }
  }
}

export default function unitConversion () {
  /**
   * 获取DPI
   * @returns {Array}
   */
  function conversionGetDPI () {
    var arrDPI = []
    if (window.screen.deviceXDPI) {
      arrDPI[0] = window.screen.deviceXDPI
      arrDPI[1] = window.screen.deviceYDPI
    } else {
      var tmpNode = document.createElement('DIV')
      tmpNode.style.cssText = 'width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden'
      document.body.appendChild(tmpNode)
      arrDPI[0] = parseInt(tmpNode.offsetWidth)
      arrDPI[1] = parseInt(tmpNode.offsetHeight)
      tmpNode.parentNode.removeChild(tmpNode)
    }
    return arrDPI
  }
  /**
   * px转换为mm
   * @param value
   * @returns {number}
   */
  let pxConversionMm = function (value) {
    var inch = value / conversionGetDPI()[0]
    var cValue = inch * 25.4
    //      console.log(c_value);
    return cValue
  }
  /**
   * mm转换为px
   * @param value
   * @returns {number}
   */
  let mmConversionPx = function (value) {
    var inch = value / 25.4
    var cValue = inch * conversionGetDPI()[0]
    //      console.log(c_value);
    return cValue
  }
  return {
    pxConversionMm,
    mmConversionPx
  }
}

const payStatus = {
  WAIT_PAY: {
    label: '待支付',
    type: 'primary'
  },
  PAYED: {
    label: '已支付',
    type: 'success'
  },
  CLOSED: {
    label: '已关闭',
    type: 'info'
  },
  CANCELED: {
    label: '已取消',
    type: 'info'
  },
  REFUNDED: {
    label: '已退款',
    type: 'danger'
  },
  REFUNDING: {
    label: '退款中',
    type: 'warning'
  }
}

export function getPayStatus (str, attr = 'label') {
  return payStatus[str] ? payStatus[str][attr] : ''
}

// 随机字符串
export function randomString (len) {
  len = len || 8
  var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
  var maxPos = $chars.length
  var pwd = ''
  for (let i = 0; i < len; i++) {
    pwd += $chars.charAt(Math.floor(Math.random() * maxPos))
  }
  return pwd
}

/**
 * 获取字符串长度，英文字符 长度1，中文字符长度2
 * @param {*} str
 */
export const getStrFullLength = (str = '') =>
  str.split('').reduce((pre, cur) => {
    const charCode = cur.charCodeAt(0)
    if (charCode >= 0 && charCode <= 128) {
      return pre + 1
    }
    return pre + 2
  }, 0)

/**
 * 截取字符串，根据 maxLength 截取后返回
 * @param {*} str
 * @param {*} maxLength
 */
export const cutStrByFullLength = (str = '', maxLength) => {
  let showLength = 0
  return str.split('').reduce((pre, cur) => {
    const charCode = cur.charCodeAt(0)
    if (charCode >= 0 && charCode <= 128) {
      showLength += 1
    } else {
      showLength += 2
    }
    if (showLength <= maxLength) {
      return pre + cur
    }
    return pre
  }, '')
}

/**
 * 获取交易响应结果，不传默认返回96位交易要素
 * @param {*} str 完整信息
 * @param {*} type 单独获取某个属性
 * @param {*} logAll 打印所有信息到控制台
 */
export function getPayResponse (str, type, logAll) {
  const scenicName = localStore.get('scenicName') || store.state.user.scenicName

  switch (scenicName) {
    case '狼山景区':
    case '军山景区':
    case '':
      let obj
      try {
        obj = JSON.parse(str)
      } catch (e) {
        return ''
      }
      if (type) {
        return obj[type]
      }
      return obj
    case '西宁景区':
      return handleXining(str, type, logAll)
  }
}

function handleXining (str, type, logAll) {
  const rescode = str.slice(0, 2)
  const cardNo = str.slice(2, 21)
  const tradeType = str.slice(21, 22)
  const total = str.slice(22, 34)
  const tradeNo = str.slice(34, 40)
  const bankNo = str.slice(40, 43)
  const referenceNo = str.slice(43, 55)
  const authCode = str.slice(55, 61)
  const batchNo = str.slice(61, 67)
  const terminalNo = str.slice(67, 75)
  const businessNo = str.slice(75, 90)
  const tradeDate = str.slice(90, 94)
  const tradeTime = str.slice(94, 100)
  const cardSign = str.slice(100, 103)
  const orderNo = str.slice(103, 167)
  const actualTotal = str.slice(167, 179)
  const discountPrice = str.slice(179, 191)
  const tradeElement = str.slice(191, 287)

  const result = {
    rescode,
    cardNo,
    tradeType,
    total,
    tradeNo,
    bankNo,
    referenceNo,
    authCode,
    batchNo,
    terminalNo,
    businessNo,
    tradeDate,
    tradeTime,
    cardSign,
    orderNo,
    actualTotal,
    discountPrice,
    tradeElement
  }

  logAll && console.table(
    [
      { name: '响应码', value: rescode, '长度': rescode.length },
      { name: '卡号', value: cardNo, '长度': cardNo.length },
      { name: '交易类型', value: tradeType, '长度': tradeType.length },
      { name: '总金额', value: total, '长度': total.length },
      { name: '交易流水号', value: tradeNo, '长度': tradeNo.length },
      { name: '发卡行号', value: bankNo, '长度': bankNo.length },
      { name: '参考号', value: referenceNo, '长度': referenceNo.length },
      { name: '授权码', value: authCode, '长度': authCode.length },
      { name: '批次号', value: batchNo, '长度': batchNo.length },
      { name: '终端号', value: terminalNo, '长度': terminalNo.length },
      { name: '商户号', value: businessNo, '长度': businessNo.length },
      { name: '交易日期', value: tradeDate, '长度': tradeDate.length },
      { name: '交易时间', value: tradeTime, '长度': tradeTime.length },
      { name: '借贷记卡标识', value: cardSign, '长度': cardSign.length },
      { name: '渠道订单号', value: orderNo, '长度': orderNo.length },
      { name: '实际金额', value: actualTotal, '长度': actualTotal.length },
      { name: '优惠金额', value: discountPrice, '长度': discountPrice.length },
      { name: '交易要素', value: tradeElement, '长度': tradeElement.length }
    ]
  )

  return type ? result[type] : result['tradeElement']
}

window.showPosDetail = (str) => {
  getPayResponse(str, null, true)
}

// 铭投拓展主题山庄项目 “门市”替换成“采购”
export function getLabelName () {
  const scenicName = localStore.get('scenicName') || store.state.user.scenicName
  switch (scenicName) {
    case '铭投拓展主题山庄':
      return '采购'
    default:
      return '门市'
  }
}

export function checkIntersection (target, base) {
  let el1 = target.getBoundingClientRect()
  let el2 = base.getBoundingClientRect()
  let isOverlay = !(el2.y + el2.height <= el1.y || el1.y + el1.height <= el2.y || el2.x + el2.width <= el1.x || el1.x + el1.width <= el2.x)
  let width
  let height
  let left
  let top
  if (isOverlay) {
    top = Math.max(el1.y, el2.y)
    left = Math.max(el1.x, el2.x)
    width = Math.min(el1.x + el1.width, el2.x + el2.width) - Math.max(el1.x, el2.x)
    height = Math.min(el1.y + el1.height, el2.y + el2.height) - Math.max(el1.y, el2.y)

    return {
      left: left + 'px',
      top: top + 'px',
      width: width + 'px',
      height: height + 'px',
      inter: (width * height) / (el1.width * el1.height)
    }
  } else {
    return {
      left: 0,
      top: 0,
      width: 0,
      height: 0,
      inter: 0
    }
  }
}

export function isJSON (data) {
  try {
    if (typeof JSON.parse(data) === 'object') {
      return true
    } else {
      return false
    }
  } catch (e) {
    return false
  }
}

export function resetServerTime (date) {
  if (!store.state.app.diffTime) {
    log.info('本地时间', moment().format('YYYY-MM-DD HH:mm:ss'))

    store.commit('SET_DIFF_TIME', date)

    log.info('时间差', store.state.app.diffTime)
    const OriginalDate = Date
    var difference = store.state.app.diffTime
    // eslint-disable-next-line no-global-assign
    Date = function () {
      var date = new OriginalDate()
      if (arguments.length === 0) {
        if (difference !== 0) {
          date = new OriginalDate(date.getTime() + difference)
        } else {
          date = new OriginalDate(date.getTime() + difference)
        }
      } else if (arguments.length === 1) { // Cannot use OriginalDate.apply(this, arguments).  See http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
        date = new OriginalDate(arguments[0])
      } else if (arguments.length === 2) {
        date = new OriginalDate(arguments[0], arguments[1])
      } else if (arguments.length === 3) {
        date = new OriginalDate(arguments[0], arguments[1], arguments[2])
      } else if (arguments.length === 4) {
        date = new OriginalDate(arguments[0], arguments[1], arguments[2], arguments[3])
      } else if (arguments.length === 5) {
        date = new OriginalDate(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4])
      } else if (arguments.length === 6) {
        date = new OriginalDate(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5])
      } else if (arguments.length === 7) {
        date = new OriginalDate(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6])
      }

      return date
    }

    Date.prototype = OriginalDate.prototype
    Date.now = function () {
      return OriginalDate.now() + difference
    }
    Date.OriginalDate = OriginalDate
    Date.UTC = OriginalDate.UTC
    Date.parse = OriginalDate.parse

    moment.now = function () {
      return store.state.app.diffTime + OriginalDate.now()
    }

    log.info('服务器时间', moment().format('YYYY-MM-DD HH:mm:ss'))
  }
}

export function getServerConfig (name) {
  if (!store.state.app.systemConfig) {
    console.error('未找到配置项', name)
    return ''
  }
  const item = store.state.app.systemConfig.find(i => i.configKey === name)
  if (!item) {
    console.error('未找到配置项', name)
    return ''
  }

  return item.configValue
}

export function isEmpty (val) {
  return !val && val !== 0
}

const desKey = 'fnFACVwC'
const key = CryptoJS.enc.Hex.parse('TgxRS8DG65EjK8cpKTiPAw==') // 密钥
const iv = CryptoJS.enc.Hex.parse('') // 偏移量

// aes加密
export function encrypt (word) {
  let encrypted = ''
  if (typeof word === 'string') {
    const key = CryptoJS.enc.Utf8.parse(desKey)
    console.log(word, desKey, 'aaaa')
    encrypted = CryptoJS.DES.encrypt(word, key, {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7
    })

    return encrypted.toString()

    // const srcs = CryptoJS.enc.Hex.parse(word)
    // // var encryptedBase64Str = CryptoJS.enc.Base64.stringify(srcs)
    // encrypted = CryptoJS.AES.encrypt(srcs, key, {
    //   mode: CryptoJS.mode.ECB,
    //   padding: CryptoJS.pad.ZeroPadding
    // })
  } else if (typeof word === 'object') {
    // 对象格式的转成json字符串
    const data = JSON.stringify(word)
    const srcs = CryptoJS.enc.Utf8.parse(data)
    encrypted = CryptoJS.AES.encrypt(srcs, key, {
      iv: iv,
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7
    })
  }
  return encrypted.ciphertext.toString()
}

// aes解密
export function decrypt (word) {
  const encryptedHexStr = CryptoJS.enc.Hex.parse(word)
  const srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr)
  const decrypt = CryptoJS.AES.decrypt(srcs, key, {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  })
  const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)
  return decryptedStr.toString()
}

// 根据 身份证获取 周岁
export function getAgeByCardId (idCard) {
  const birthday = idCard.substr(6, 8)
  const year = Number(birthday.substr(0, 4))
  const month = Number(birthday.substr(4, 2))
  const day = Number(birthday.substr(6, 2))

  const currentDate = new Date()
  const currentYear = currentDate.getFullYear()
  const currentMonth = currentDate.getMonth() + 1
  const currentDay = currentDate.getDate()

  let age = currentYear - year

  if (currentMonth < month || (currentMonth === month && currentDay < day)) {
    age--
  }

  return age
}

/* 导入excel文件 */

/**
 * 导入excel文件实现思路分析
 *
 * 1.使用html支持上传标签从本地获取文件，例如type为file的input，el-upload等。
 * 2.利用FileReader将文件读取为二进制字符串。
 * 3.使用XLSX插件的XLSX.read()方法，将二进制字符串转换成excel文件的工作蒲对象workbook（简写成wb）。
 * 4.通过XLSX.utils.sheet_to_json()方法，从wb中获取第一张 Sheets表格数据并将其转换为json数据。
 * 5.重组json数据生成数组，即是根据自己的定义的列字段名，重新组成符合自己需求的json数据。因为从excel中提取的数据是没有字段名或字段名不符合要求的，
 * 而我们需要渲染在页面表格中又确实需要合适的字段名。
 */

/**
 * @param file 文件流
 * @param tableTemplate 要导入的表格模板，一个数组，如：
 * tableTemplate: ['userCode', 'userName', 'department', 'major', 'position']，其中的值
 * 为表格的字段名，注意字段的顺序应与实际的导入excel一致。
 */

export function importExcel (file, tableTemplate) {
  return new Promise((resolve, reject) => {
    let f = file.raw // 获取文件内容
    // 通过DOM取文件数据
    let rABS = false // 是否将文件读取为二进制字符串
    let reader = new FileReader()
    FileReader.prototype.readAsBinaryString = function (f) {
      let binary = ''
      let rABS = false // 是否将文件读取为二进制字符串
      let wb // 读取完成的数据
      let outdata
      let reader = new FileReader()
      reader.onload = function (e) {
        let bytes = new Uint8Array(reader.result)
        let length = bytes.byteLength
        for (let i = 0; i < length; i++) {
          binary += String.fromCharCode(bytes[i])
        }
        let XLSX = require('xlsx')
        if (rABS) {
          wb = XLSX.read(btoa(binary), { // 手动转化
            type: 'base64'
          })
        } else {
          wb = XLSX.read(binary, {
            type: 'binary'
          })
        }
        outdata = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]) // outdata就是表格中的值

        let arr = []
        // 下面是数据解析提取逻辑
        if (tableTemplate.length > 0) {
          let tempArr = Object.keys(outdata[0])
          let tempArrNew = []
          for (let i in tempArr) {
            for (let k in tableTemplate) {
              if (i === k) {
                tempArrNew.push({ fieldE: tableTemplate[k], fieldC: tempArr[i] })
              }
            }
          }

          tempArr = tempArrNew
          outdata.map(item => {
            let obj = {}
            tempArr.map(temp2 => {
              obj[temp2.fieldE] = item[temp2.fieldC]
            })
            arr.push(obj)
          })
        }

        resolve(arr)
      }
      reader.readAsArrayBuffer(f)
    }

    if (rABS) {
      reader.readAsArrayBuffer(f)
    } else {
      reader.readAsBinaryString(f)
    }
  })
}
