import Vue from 'vue'
import Select2 from '@/components/FormFields/Select2'
import NestedField from '@/components/AutoDataForm/components/NestedField'
import Swicher from '@/components/FormFields/Swicher'
import rules from '@/components/DataForm/rules'
import { assignIfNot } from '@/utils/common'

export class FormFieldGenerator {
  constructor() {
    this.groups = []
  }
  generateFieldByType(type, field, fieldMeta, fieldRemoteMeta) {
    switch (type) {
      case 'choice':
        type = 'radio-group'
        if (!fieldRemoteMeta.read_only) {
          field.options = fieldRemoteMeta.choices.map(v => {
            return { label: v.display_name, value: v.value }
          })
        }
        break
      case 'multiple choice':
        field.el.choices = fieldRemoteMeta['choices']
        break
      case 'datetime':
        type = 'date-picker'
        field.el = {
          type: 'datetime'
        }
        break
      case 'field':
        type = ''
        field.component = Select2
        if (fieldRemoteMeta.required) {
          field.el.clearable = false
        }
        break
      case 'string':
        type = 'input'
        if (!fieldRemoteMeta['max_length']) {
          field.el.type = 'textarea'
          field.el.rows = 3
        }
        if (fieldRemoteMeta['write_only']) {
          field.el.type = 'password'
        }
        break
      case 'boolean':
        type = ''
        field.component = Swicher
        break
      case 'nested object':
        type = 'nestedField'
        field.component = NestedField
        field.label = ''
        field.labelWidth = 0
        field.el.fields = this.generateNestFields(field, fieldMeta, fieldRemoteMeta)
        field.el.errors = {}
        Vue.$log.debug('All fields in generate: ', field.el.allFields)
        break
      default:
        type = 'input'
        break
    }
    if (type === 'radio-group') {
      if (!fieldRemoteMeta.read_only) {
        const options = fieldRemoteMeta.choices.map(v => {
          return { label: v.display_name, value: v.value }
        })
        if (options.length > 4) {
          type = 'select'
          field.el.filterable = true
        }
      }
    }
    field.type = type
    return field
  }
  generateNestFields(field, fieldMeta, fieldRemoteMeta) {
    const fields = []
    const nestedFields = fieldMeta.fields || []
    const nestedFieldsMeta = fieldMeta.fieldsMeta || {}
    const nestedFieldsRemoteMeta = fieldRemoteMeta.children || {}
    for (const name of nestedFields) {
      const f = this.generateField(name, nestedFieldsMeta, nestedFieldsRemoteMeta)
      fields.push(f)
    }
    Vue.$log.debug('NestFields: ', fields)
    return fields
  }
  generateFieldByName(name, field) {
    switch (name) {
      case 'email':
        field.el.type = 'email'
        break
      case 'password':
        field.el.type = 'password'
        break
      case 'comment':
        field.el.type = 'textarea'
        break
    }
    return field
  }
  generateFieldByOther(field, fieldMeta, fieldRemoteMeta) {
    const filedRules = field.rules || []
    if (fieldRemoteMeta.required) {
      if (field.type === 'input') {
        filedRules.push(rules.Required)
      } else {
        filedRules.push(rules.RequiredChange)
      }
    }
    field.rules = filedRules
    return field
  }
  generateField(name, fieldsMeta, remoteFieldsMeta) {
    let field = { id: name, prop: name, el: {}, attrs: {}, rules: [] }
    const remoteFieldMeta = remoteFieldsMeta[name] || {}
    const fieldMeta = fieldsMeta[name] || {}
    field.label = remoteFieldMeta.label
    field.helpText = remoteFieldMeta.help_text
    field = this.generateFieldByType(remoteFieldMeta.type, field, fieldMeta, remoteFieldMeta)
    field = this.generateFieldByName(name, field)
    field = this.generateFieldByOther(field, fieldMeta, remoteFieldMeta)
    const el = assignIfNot(fieldMeta.el || {}, field.el)
    const rules = fieldMeta.rules || field.rules
    field = Object.assign(field, fieldMeta)
    field.el = el
    field.rules = rules
    _.set(field, 'attrs.error', '')
    // Vue.$log.debug('Generate field: ', name, field)
    return field
  }
  generateFieldGroup(field, fieldsMeta, remoteFieldsMeta) {
    const [groupTitle, fields] = field
    this.groups.push({
      id: groupTitle,
      title: groupTitle,
      name: fields[0],
      fields: fields
    })
    return this.generateFields(fields, fieldsMeta, remoteFieldsMeta)
  }
  generateFields(_fields, fieldsMeta, remoteFieldsMeta) {
    let fields = []
    for (let field of _fields) {
      if (field instanceof Array) {
        const items = this.generateFieldGroup(field, fieldsMeta, remoteFieldsMeta)
        fields = [...fields, ...items]
      } else if (typeof field === 'string') {
        field = this.generateField(field, fieldsMeta, remoteFieldsMeta)
        fields.push(field)
      } else if (field instanceof Object) {
        if (this.errors) {
          this.errors[field.prop] = ''
        }
        fields.push(field)
      }
    }
    return fields
  }
}
