import Source from './source'
import * as ss from 'simple-statistics'
import _ from 'lodash'
import createFilter from './filter'
/**
 * 画布上各组件的通用对象，主要是各部件的通用函数，
 * 例如组件的缩放、平移、上移、下移、删除等
 */

class TableSource extends Source {
  constructor(...params) {
    super(...params)
  }

  reduceData(data) {
    //数据清洗
    if (!this.transform) {
      return this.eventParent.fire('source.load', { id: this.id, data: data })
    }
    this.transform.forEach(t => {
      switch (t.type) {
        case 'filter':
          data = this.filter(data, t.condition || t.callback)
          break
        case 'aggregate':
          data = this.aggregate(data, t.fields, t.operations, t.as, t.groupBy)
          break
        case 'sort':
          data = this.sort(data, t.fields, t.orders)
          break
        case 'map':
          data = this.map(data, t.field, t.order, t.params)
          break
        case 'select_field':
          data = this.fieldsSelect(data, t.fields)
          break
        default:
          break
      }
    })
    this.eventParent.fire('source.load', { id: this.id, data: data })
  }

  filter(data, params) {
    let result = data
    if (typeof params === 'function') {
      result = data.filter(params)
    } else if (typeof params === 'object') {
      /*let filter = params;
      let condition = filter.join('');*/
      let filterActions = createFilter(params)
      result = data.filter(filterActions)
    }
    return result
  }

  map(data, field, order, params) {
    if (!field || !order) {
      return data
    }
    data = data.map(d => {
      switch (order) {
        case 'toNumber':
          d[field] = Number(d[field])
          break
        case 'toString':
          d[field] = String(d[field])
          break
        case 'toUppercase':
          if (typeof d[field] !== 'string') {
            console.warn('Can not convert non-string to uppercase')
            return
          }
          d[field] = d[field].toUpperCase()
          break
        case 'toLowercase':
          if (typeof d[field] !== 'string') {
            console.warn('Can not convert non-string to lowercase')
            return
          }
          d[field] = d[field].toLowerCase()
          break
        case 'add':
          d[field] += params.value
          break
        case 'subtract':
          d[field] -= params.value
          break
        case 'multiply':
          d[field] *= params.value
          break
        case 'divide':
          d[field] /= params.value
          break
        default:
          break
      }
      return d
    })
    return data
  }

  aggregate(data, fields, operations, as, groupBy) {
    let result = []
    let groups = {}
    data.forEach(d => {
      if (groups[d[groupBy]]) {
        groups[d[groupBy]].push(d)
      } else {
        groups[d[groupBy]] = [d]
      }
    })
    for (let key in groups) {
      let item = groups[key][0]
      fields.forEach((f, index) => {
        if (!operations[index]) {
          return
        }
        let arr = []
        groups[key].forEach(d => {
          arr.push(d[f])
        })
        let newField = as[index] || f + '_' + operations[index]
        item[newField] = ss[operations[index]](arr)
      })
      result.push(item)
    }
    return result
  }

  sort(data, fields, orders) {
    return _.orderBy(data, fields, orders)
  }

  fieldsSelect(data, fields) {
    if (!fields || !fields.length) {
      return data
    }
    return data.map(d => {
      let temp = {}
      fields.forEach(field => {
        if (!field.name) {
          return
        }
        temp[field.as || field.name] = d[field.name]
      })
      return temp
    })
  }
}

export default TableSource
