import Admin from '../constants/admin'
import { customAlphabet } from 'nanoid'

var util = new Object()

util.getScale = function(el, mode, width, height) {
  let scaleX, scaleY
  let rect = el.getBoundingClientRect()
  if (mode === 'width') {
    scaleX = scaleY = rect.width / width
    //scaleX = scaleY = scale > 1 ? 1 : scale;
  } else if (mode === 'height') {
    scaleX = scaleY = rect.height / height
    //scaleX = scaleY = scale > 1 ? 1 : scale;
  } else if (mode === 'original') {
    scaleX = scaleY = 1
  } else {
    scaleX = rect.width / width
    scaleY = rect.height / height
  }
  return { scaleX, scaleY }
}

util.extend = function(dest, ...sources) {
  for (const src of sources) {
    for (const k in src) {
      dest[k] = src[k]
    }
  }
  return dest
}

util.endsWith = function(string, suffix) {
  return string.indexOf(suffix, string.length - suffix.length) !== -1
}

util.isIdExist = function(id, layers) {
  for (let i = 0; i < layers.length; i++) {
    if (layers[i].id === id) {
      return true
    }
  }
  return false
}

util.unique = function(arr) {
  var res = []
  var json = {}
  for (var i = 0; i < arr.length; i++) {
    if (!json[arr[i]]) {
      res.push(arr[i])
      json[arr[i]] = 1
    }
  }
  return res
}

/**
 * 从一个对象中扫描其中的占位符，返回占位符变量的数组
 * @obj {Object} 扫描占位符的对象
 */
util.scanPlaceholder = function(obj = {}) {
  let results = []
  for (let key in obj) {
    if (typeof obj[key] === 'string') {
      let vars = obj[key].match(/\{\{([^\}]+)\}\}/g)  //eslint-disable-line
      if (vars && vars.length > 0) {
        for (let i = 0; i < vars.length; i++) {
          let name = vars[i].replace(/\{\{/g, '').replace(/\}\}/g, '')
          if (results.indexOf(name) === -1) {
            results.push(name)
          }
        }
      }
    } else if (typeof obj[key] === 'object') {
      let tem = util.scanPlaceholder(obj[key])
      results = results.concat(tem)
    }
  }
  return util.unique(results)
}

/**
 * 将target中的占位符用opts中的值进行替换
 * @target {Object} 目标对象
 * @opts {Object} 占位符的值
 */
util.replacePlaceholder = function(target, opts) {
  for (let key in target) {
    if (typeof target[key] === 'string') {
      let vars = target[key].match(/\{\{([^\}]+)\}\}/g) //eslint-disable-line
      if (vars && vars.length > 0) {
        for (let i = 0; i < vars.length; i++) {
          let name = vars[i].replace(/\{\{/g, '').replace(/\}\}/g, '')
          target[key] = target[key].replace(vars[i], opts[name])
        }
      }
    } else if (typeof target[key] === 'object') {
      util.replacePlaceholder(target[key], opts)
    }
  }
}

util.getType = function(obj) {
  //tostring会返回对应不同的标签的构造函数
  var toString = Object.prototype.toString
  var map = {
    '[object Boolean]': 'boolean',
    '[object Number]': 'number',
    '[object String]': 'string',
    '[object Function]': 'function',
    '[object Array]': 'array',
    '[object Date]': 'date',
    '[object RegExp]': 'regExp',
    '[object Undefined]': 'undefined',
    '[object Null]': 'null',
    '[object Object]': 'object'
  }
  if (obj instanceof Element) {
    return 'element'
  }
  return map[toString.call(obj)]
}

util.deepCopy = function(initalObj) {
  var type = util.getType(initalObj)
  var obj
  if (type === 'array') {
    obj = []
  } else if (type === 'object') {
    obj = {}
  } else {
    //不再具有下一层次
    return initalObj
  }
  if (type === 'array') {
    for (var i = 0, len = initalObj.length; i < len; i++) {
      obj.push(util.deepCopy(initalObj[i]))
    }
  } else if (type === 'object') {
    for (var key in initalObj) {
      obj[key] = util.deepCopy(initalObj[key])
    }
  }
  return obj
}

util.isDOM = function(obj) {
  if (typeof HTMLElement === 'object') {
    return obj instanceof HTMLElement
  } else {
    return (
      obj &&
      typeof obj === 'object' &&
      obj.nodeType === 1 &&
      typeof obj.nodeName === 'string'
    )
  }
}

util.hex2rgb = function(color) {
  var r = parseInt(color.substr(1, 2), 16)
  var g = parseInt(color.substr(3, 2), 16)
  var b = parseInt(color.substr(5, 2), 16)
  return new Array(r, g, b)
}

util.rgb2hex = function(rgb) {
  var s = '#'
  for (var i = 0; i < 3; i++) {
    var c = Math.round(rgb[i]).toString(16)
    if (c.length == 1) c = '0' + c
    s += c
  }
  return s
}

util.gradient = function(type, direction, ...colors) {
  if (type === 'css') {
    if (direction === 'center') {
      return `radial-gradient(${colors.toString()})`
    } else {
      return `linear-gradient(to ${direction}, ${colors.toString()})`
    }
  } else if (type === 'echarts') {
    let gradientColors = []
    colors.forEach((c, index) => {
      gradientColors.push({
        offset: index / (colors.length - 1),
        color: c
      })
    })
    if (direction === 'center') {
      return new echarts.graphic.RadialGradient(0.5, 0.5, 1.0, gradientColors)
    } else {
      let right = direction.indexOf('right') !== -1 ? 1 : 0
      let bottom = direction.indexOf('bottom') !== -1 ? 1 : 0
      let left = direction.indexOf('left') !== -1 ? 1 : 0
      let top = direction.indexOf('top') !== -1 ? 1 : 0
      // eslint-disable-next-line
      return new echarts.graphic.LinearGradient(
        right,
        bottom,
        left,
        top,
        gradientColors
      )
    }
  } else if (type === 'svg') {
    let id = util.generateId()
    let stops = []
    colors.forEach((c, index) => {
      stops.push(
        `<stop offset="${
          index ? index / (colors.length - 1) : 0
        }" stop-color="${c}" stop-opacity="1"/>`
      )
    })
    let x1 = direction.indexOf('left') !== -1 ? 0 : 100
    let x2 = direction.indexOf('right') !== -1 ? 0 : 100
    let y1 = direction.indexOf('top') !== -1 ? 0 : 100
    let y2 = direction.indexOf('bottom') !== -1 ? 0 : 100
    let gradient = `<linearGradient id="${id}" x1="${x1}%" y1="${y1}%" x2="${x2}%" y2="${y2}%">
      ${stops.join('')}
    </linearGradient>`
    return { id, gradient }
  }
  return null
}

util.parseUrl = function(url) {
  var parser = document.createElement('a')
  parser.href = url
  var paramPart = parser.search.substr(1).split('&')
  parser.query = paramPart.reduce(function(res, item) {
    var parts = item.split('=')
    res[parts[0]] = parts[1]
    return res
  }, {})
  var { protocol, hostname, port, pathname, search, hash, host, query } = parser
  return { protocol, hostname, port, pathname, search, hash, host, query }
}

util.mergeObjs = function(def, obj) {
  if (!obj) {
    return def
  } else if (!def) {
    return obj
  }

  for (var i in obj) {
    // 是一个对象
    if (
      def[i] &&
      typeof def[i] === typeof obj[i] &&
      obj[i] != null &&
      obj[i].constructor == Object
    ) {
      def[i] = util.mergeObjs(def[i], obj[i])
    } else {
      def[i] = obj[i]
    }
  }
  return def
}

util.getAttributeByCode = function(code) {
  // 根据行政区划代码获得行政区划名称和中心经纬度
  code = String(code)
  let level = util.getAdminType(code)
  if (level === 1) {
    return {
      name: Admin[code].name,
      coord: Admin[code].cp
    }
  } else if (level === 2) {
    let province = Admin[code.substr(0, 2) + '0000']
    return {
      name: province.children[code].name,
      coord: province.children[code].cp
    }
  } else {
    let province = Admin[code.substr(0, 2) + '0000']
    if (province.children[code]) {
      return {
        name: province.children[code].name,
        coord: province.children[code].cp
      }
    } else {
      let city = province.children[code.substr(0, 4) + '00']
      if (city) {
        return {
          name: city.children[code].name,
          coord: city.children[code].cp
        }
      } else {
        return null
      }
    }
  }
}

util.getAdminDataByCode = function(code) {
  code = String(code)
  let level = util.getAdminType(code)
  if (level === 1) {
    return Admin[code].children
  } else if (level === 2) {
    let province = Admin[code.substr(0, 2) + '0000']
    return province.children[code].children || {}
  } else {
    let province = Admin[code.substr(0, 2) + '0000']
    if (province.children[code]) {
      return province.children[code].children || {}
    } else {
      let city = province.children[code.substr(0, 4) + '00']
      if (city) {
        return city.children[code].children || {}
      } else {
        return {}
      }
    }
  }
}
// 给定 admin code，返回 admin 级别
// 省市县的 admin code 是6位格式，乡镇为8位格式
// 返回值：1 -- 省；2 -- 市；3 -- 县；4 -- 乡镇; 0 -- 无效 codeName
util.getAdminType = function(codeName) {
  if (codeName.length == 8) {
    return 4
  }
  if (codeName === '156') {
    return 0
  }
  // check valid
  if (codeName.length != 6) {
    return -1
  }
  // 省级行政区的后四位为0
  if (/0000$/.test(codeName)) {
    return 1
  }
  // 市级行政的后两位为0
  if (/00$/.test(codeName)) {
    return 2
  }
  return 3
}

// 将角度归一化到0-360度
util.formatAngle = function(angle) {
  let t = angle % 360
  if (t < 0) {
    return t + 360
  } else {
    return t
  }
}

util.pickColData = function(field, data) {
  let result = []
  data.forEach(d => {
    result.push(d[field])
  })
  return result
}

util.generateId = function() {
  // 生成随机id
  const nanoid = customAlphabet(
    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
    11
  )
  return nanoid()
}

util.findComponent = function(components, id) {
  // 从组件列表里查找指定id的组件，包括容器内的子组件
  let result = null
  for (let i = 0; i < components.length; i++) {
    if (components[i].id === id) {
      result = components[i]
      break
    } else if (
      components[i].paint.components &&
      components[i].paint.components.length
    ) {
      let subComponents = components[i].paint.components
      for (let j = 0; j < subComponents.length; j++) {
        if (subComponents[j].id === id) {
          result = subComponents[j]
          break
        }
      }
      if (result) {
        break
      }
    }
  }
  return result
}

util.findComponentIndex = function(components, id) {
  // 从组件列表里查找指定id的组件索引，包括容器内的子组件
  // 如果为子组件，则index是一个2个数的数组，例如[3,2]，表示第4个组件的第3个子组件
  let index = -1
  for (let i = 0; i < components.length; i++) {
    if (components[i].id === id) {
      index = i
      break
    } else if (
      components[i].paint.components &&
      components[i].paint.components.length
    ) {
      let subComponents = components[i].paint.components
      for (let j = 0; j < subComponents.length; j++) {
        if (subComponents[j].id === id) {
          index = [i, j]
          break
        }
      }
      if (index !== -1) {
        break
      }
    }
  }
  return index
}

export default util
