export default {
  install(Vue) {
    // Array ext.
    Array.prototype.first = function(predicate) {
      if (predicate == null || typeof predicate !== 'function') {
        return this.length ? this[0] : null
      }
      for (let i = 0; i < this.length; i++) {
        const item = this[i]
        if (predicate(item)) return item
      }
    }
    Array.prototype.last = function(predicate) {
      if (predicate == null || typeof predicate !== 'function') {
        return this.length ? this[this.length - 1] : null
      }
      for (let i = this.length - 1; i >= 0; i--) {
        const item = this[i]
        if (predicate(item)) return item
      }
    }
    Array.prototype.groupBy = function(propGetter, groupName = 'label', listName = 'options') {
      const results = []
      this.forEach(item => {
        const groupValue = propGetter(item)
        let exists = results.find(i => i[groupName] == groupValue)
        if (!exists) {
          exists = {}
          exists[groupName] = groupValue
          exists[listName] = []
          results.push(exists)
        }
        exists[listName].push(item)
      })

      return results
    }
    Array.prototype.remove = function(item) {
      // remove first match item in array
      const idx = this.findIndex(i => i == item)
      if (idx == -1) return
      this.splice(idx, 1)
    }
    Array.prototype.sum = function(propGetter = null) {
      let result = 0
      this.forEach(item => {
        if (propGetter) {
          result += propGetter(item) * 1
        } else {
          result += item * 1
        }
      })
      return result
    }

    // String
    String.prototype.castObject = function() {
      // cast if it is json
      try {
        return JSON.parse(this)
      } catch (e) {
        console.log('extension `castObject` failed, will return raw value.', e)
        return this
      }
    }
    String.prototype.tailingFix = function(fix) {
      return this.endsWith(fix) ? this : this + fix
    }

    // Global func.
    Vue.prototype.deepClone = function(obj) {
      if (!obj) return obj
      return JSON.parse(JSON.stringify(obj))
    }
    // 动态表转objects
    Vue.prototype.reverseDynamicTableToObjects = function({ columns, rows }) {
      return rows.map(row => {
        const obj = {}
        columns.forEach((col, idx) => obj[col] = row[idx])
        return obj
      })
    }
    Vue.prototype.dynamicTableExchangeRowColumn = function({ columns, rows }) {
      let newColumns = []
      let newRows = []
      for (let rowIdx = 0; rowIdx < columns.length; rowIdx++) {
        const rowName = columns[rowIdx]
        const newRow = [rowName]
        for (let colIdx = 0; colIdx < rows.length; colIdx++) {
          const row = rows[colIdx]
          const val = rowIdx < row.length ? row[rowIdx] : ''
          newRow.push(val)
        }
        if (rowIdx == 0) {
          newColumns = newRow
        } else {
          newRows.push(newRow)
        }
      }
      return {
        columns: newColumns,
        rows: newRows
      }
    }
    Vue.prototype.convertStandardTree = function(root, labelKey = 'label', valueKey = 'value', childrenKey = 'children') {
      const convertor = (node) => ({
        label: node[labelKey],
        value: node[valueKey],
        children: node[childrenKey]?.map(convertor)
      })
      const arrRoot = Array.isArray(root) ? root : [root]
      return arrRoot.map(convertor)
    }
  }
}
