<template>
  <v-form ref="form" v-model="valid" class="login-form" @submit.native.prevent>
      <div>
          <v-row dense no-gutters class="justify-space-between">
            <template v-for="(item, index) in items">
              <slot :name="item.prevSlot"></slot>
              <v-col :key="item.key" v-if="!item.hide" :cols="item.col || '12'" class="position">
                <template v-if="item.slotTitle">
                  <div :class="item.class" :style="item.slotTitleStyle">{{ item.slotTitle }}</div>
                </template>
                <div :class="item.flexStyle || 'flex-row'" class="px-2 d-flex">
                  <v-text-field
                      v-if="['text', 'password', 'number'].includes(item.type)"
                      v-bind="item"
                      v-model="query[item.key]"
                      :hide-details="item.hideDetails ?? false"
                      :dense="item.dense ?? true"
                      :style="{width: item.width}"
                      :placeholder="item.placeholder || item.label"
                      :outlined="item.outlined ?? true"
                      hide-spin-buttons
                      @wheel.native="$event => handleWheel($event, item)"
                      @keyup.enter.native="item.keyupEnterNative && item.keyupEnterNative(index)"
                      @click="item.click && item.click(index)"
                      @click:append="item.clickAppend && item.clickAppend(index)"
                      @change="handleChange(item)"
                      @input="item.onInput && item.onInput(item)"
                  />
                  <v-autocomplete
                      v-if="item.type === 'autocomplete'"
                      v-model="query[item.key]"
                      :attach="!item.noAttach"
                      :placeholder="item.placeholder || item.label"
                      :item-text="item.itemText || 'label'"
                      :item-value="item.itemValue || 'value'"
                      :outlined="item.outlined ?? true"
                      :dense="item.dense ?? true"
                      :return-object="item.returnObject || false"
                      :search-input.sync="item.searchInput"
                      :hide-details="item.hideDetails ?? false"
                      :no-data-text="item.noDataText || 'No data available'"
                      v-bind="item"
                      @change="handleChange(item)"
                  >
                    <template v-if="item.slotAppendItem" v-slot:append-item>
                      <slot :name="item.slotAppendItem" :item="item"></slot>
                    </template>
                    <template v-if="item.prependItem" #prepend-item>
                      <slot :name="item.prependItem" :item="item"></slot>
                    </template>
                  </v-autocomplete>
                  <v-textarea
                    v-if="item.type === 'textarea'"
                    :rules="item.rules"
                    v-model="query[item.key]"
                    :label="item.label"
                    :placeholder="item.placeholder || item.label"
                    :no-resize="!item.resize"
                    :outlined="item.outlined ?? true"
                    :readonly="item.readonly"
                    :dense="item.dense ?? true"
                    :rows="item.rows || 3"
                    :disabled="item.disabled"
                    @change="handleChange(item)"
                  ></v-textarea>
                  <v-radio-group
                    v-if="item.type === 'ifRadio'"
                    v-model="query[item.key]"
                    :disabled="item.disabled"
                    :style="item.selfStyle"
                    :class="item.selfClass"
                    mandatory
                    row
                    @change="handleChange(item)"
                  >
                    <template v-if="item.label" v-slot:label>
                      <div :style="`width: ${item.width || 120}px;`">{{ item.label }}</div>
                    </template>
                    <v-radio
                      v-for="radio in item.items"
                      :key="`${item.key}_radio_${radio.label}`"
                      :readonly="radio.readonly"
                      :label="radio.label"
                      :value="radio.value"
                      class="mr-8"
                    ></v-radio>
                  </v-radio-group>
                  <template v-if="item.type === 'checkbox'">
                    <div style="width: 120px;" class="mt-4 label text-left">{{ item.label }}</div>
                    <div :style="item.style">
                      <v-checkbox
                        v-model="query[item.key]"
                        v-for="k in item.items"
                        :key="k.key"
                        :label="k.label"
                        :color="item.color"
                        :value="k.value"
                        :readonly="k.readonly"
                        hide-details
                        :multiple="true"
                        class="mr-3"
                      ></v-checkbox>
                    </div>
                  </template>
                  <v-file-input
                    v-if="item.type === 'upload'"
                    :prepend-icon="item.prependIcon || ''"
                    :append-icon="item.appendIcon"
                    :append-outer-icon="item.appendOuterIcon"
                    :show-size="item.showSize"
                    :outlined="item.outlined ?? true"
                    :dense="item.dense ?? true"
                    v-model="query[item.key]"
                    :placeholder="item.placeholder || item.label"
                    :hint="item.hint"
                    :rules="item.rules"
                    :label="item.label"
                    :persistent-hint="item.persistentHint"
                    :loading= "item.loading"
                    :disabled="item.disabled"
                    :multiple="item.multiple"
                    :success="item.success"
                    :error="item.error"
                    :accept="item.accept || '.xlsx, .xls, .csv, .pdf, .txt, .doc'"
                    @change="handleChange(item)"
                  >
                    <template v-if="item.selfAppend" #append>
                      <slot :name="item.selfAppend" :data="query[item.key]"></slot>
                    </template>
                  </v-file-input>
                  <v-color-picker
                    v-if="item.type === 'colorPicker'"
                    class="mb-5"
                    v-model="query[item.key]"
                    :elevation="item.elevation || 5"
                    :dot-size="item.dotSize || 25"
                    :show-swatches="item.showSwatches || false"
                    swatches-max-height="200"
                    :mode="item.mode || 'hexa'"
                    :hide-mode-switch="true"
                    @input="item.change"
                  />
                  <template v-if="item.type === 'switch'">
                    <span v-if="item.describe"> {{ item.describe }} </span>
                    <span class="ml-2" v-if="item.trueLabel"> {{ item.trueLabel }}</span>
                    <v-switch
                      dense hide-details class="mt-0 ml-2 pa-0"
                      v-model="query[item.key]"
                      :label="item.label"
                      :disabled="item.disabled || false"
                      :color="item.color || 'primary'"
                      :true-value="(item.trueValue !== undefined) ? item.trueValue : true"
                      :false-value="(item.falseValue !== undefined) ? item.falseValue : false"
                    ></v-switch>
                    <span v-if="item.falseLabel"> {{ item.falseLabel }} </span>
                  </template>
                  <template v-if="item.type === 'date'">
                    <div class="d-flex" style="margin-bottom: 22px;flex: 1;">
                      <span v-if="item.width !== -1" class="label d-flex align-center" :style="`width: ${item.width || 120}px;`">{{ item.label }}</span>
                      <date-picker
                        :is-valid="isValid"
                        :option="{ ...item.option, disabled: item.disabled }"
                        v-model="query[item.key]"
                        :style="item.style"
                        @change="query[item.key] = $event; handleChange(item); handleCheck(item)"></date-picker>
                    </div>
                  </template>
                  <template v-if="item.type === 'dataPicker'">
                    <m-data-picker
                      v-model="query[item.key]"
                      style="flex: 1"
                      :label="item.label"
                      :placeholder="item.placeholder || item.label"
                      :multiple="item.multiple"
                      :collapse-tags="item.collapseTags"
                      :max-collapse-tags="item.maxCollapseTags"
                      :item-children="item.itemChildren ?? 'children'"
                      :item-label="item.itemLabel ?? 'label'"
                      :item-value="item.itemValue ?? 'value'"
                      :items="item.items"
                      :rules="item.rules"
                      @change="handleChange(item)"
                    ></m-data-picker>
                  </template>
                  <template v-if="item.slotName">
                      <slot :name="item.slotName" :item="item"></slot>
                  </template>
                </div>
              </v-col>
              <slot :name="item.nextSlot"></slot>
            </template>
          </v-row>
      </div>
      <slot></slot>
  </v-form>
</template>

<script>
import DatePicker from '@/components/Form/datePicker.vue'
import MDataPicker from '@/components/MDataPicker'
export default {
  name: 'MForm',
  components: { DatePicker, MDataPicker },
  props: {
    value: {
      type: Object,
      default: () => ({})
    },
    items: {
      type: Array,
      default: () => [],
      required: true
    }
  },
  data () {
    return {
      query: {
        ...this.value
      },
      inputUpdateValue: '',
      valid: false,
      isValid: true
    }
  },
  watch: {
    value: {
      handler (val) {
        this.query = val
      },
      deep: true
    },
    query: {
      handler (val) {
        this.$emit('input', val)
      },
      deep: true
    }
  },
  methods: {
    handleWheel (event, item) {
      if (item.type !== 'number') return
      event.preventDefault()
      if (event.deltaY > 0) {
        typeof this.query === 'number' && this.query[item.key]--
      } else {
        typeof this.query === 'number' && this.query[item.key]++
      }
      this.handleChange(item)
    },
    handleCheck (e) {
      if (e.type !== 'date' || e.hide || !e.rules) return
      const rules = e.rules[0]
      const check = rules(this.query[e.key])
      if (typeof check === 'string') {
        e.option.error = true
        e.option.errorMsg = check
        return
      }
      e.option.error = false
      e.option.errorMsg = null
    },
    validateTime () {
      this.isValid = true
      this.items.forEach((e, index) => {
        if (e.type !== 'date' || e.hide || !e.rules) return
        const rules = e.rules[0]
        const check = rules(e.value)
        if (typeof check === 'string') {
          this.isValid = false
          e.option.error = true
          e.option.errorMsg = check
        } else {
          e.option.error = false
          e.option.errorMsg = null
        }
      })
      return this.isValid
    },
    validate () {
      const form = this.$refs.form.validate()
      const time = this.validateTime()
      return form && time
    },
    inputUpdateAutocomplete (val) {
      this.$emit('inputUpdateAutocomplete', val)
    },
    resetValidation () {
      this.$refs.form.resetValidation()
    },
    reset () {
      this.$refs.form.reset()
    },
    handleChange (item) {
      if (item.type === 'date' && this.query[item.key]) item.option.validate = false
      if (item?.change) item.change(this.query[item.key], item)
      this.$emit('change', false)
    }
  }
}
</script>

<style lang="scss" scoped>
.position {
  position: relative;
}
.label {
  font-size: 14px;
  color: rgba(0, 0, 0, .6);
}
</style>
