<template>
  <van-cell class="ibps-address ibps-p-0" :border="border">
    <van-field
      ref="input"
      v-model="inputValue"
      :label="label"
      :name="name"
      :size="size"
      :placeholder="placeholder"
      :border="!hasStreet"
      :disabled="disabled"
      :required="required"
      :clearable="clearable"
      :clickable="clickable"
      :is-link="isLink"
      :error="error"
      :error-message="errorMessage"

      :arrow-direction="arrowDirection"
      :label-class="labelClass"
      :label-width="labelWidth"
      :label-align="labelAlign"
      :input-align="inputAlign"
      :error-message-align="errorMessageAlign"
      :autosize="autosize"
      :left-icon="leftIcon"
      :right-icon="rightIcon"
      :icon-prefix="iconPrefix"
      :rules="editable?rules:null"
      readonly
      @click-input="onClick"
    >
      <template #label>
        {{ label }}<van-icon v-if="desc && descPosition==='lableIcon'" name="warning" class="ibps-dialog-icon" @click="$action.descDialog({ title:label, message:desc })" />
      </template>
      <template v-if="editable" #right-icon>
        <van-icon
          v-if="showClear"
          name="clear"
          class="van-field__clear"
          @click.native.stop="onRightIconClick"
        />
        <!-- <van-icon
          v-else
          :name="showPopup?'arrow-up':'arrow-down'"
          @click.native.stop="onClick"
        /> -->
        <!-- <van-icon
          v-else
          :name="showPopup?'arrow-up':'arrow-down'"
          @click.native.stop="onClick"
        /> -->
        <van-icon
          v-else
          :name="rightIcon"
          @click.native.stop="onClick"
        />
        <van-popup
          v-model="showPopup"
          position="bottom"
          get-container="body"
        >
          <ibps-area
            v-model="areaValue"
            :title="title"
            :area-data="areaData"
            :top="top"
            :top-val="topVal"
            :level="level"
            @confirm="onConfirm"
            @cancel="onCancel"
          />
        </van-popup>
      </template>
    </van-field>
    <template v-if="hasStreet">
      <van-field
        ref="street"
        v-model="street"
        label=" "
        :colon="false"
        :border="border"
        :size="size"
        :placeholder="editable?streetPlaceholder:''"

        :readonly="readonly"
        :disabled="disabled"
        :clearable="clearable"
        :clickable="clickable"
        :is-link="isLink"
        :error="error"
        :error-message="errorMessage"

        :arrow-direction="arrowDirection"
        :label-class="labelClass"
        :label-width="labelWidth"
        :label-align="labelAlign"
        :input-align="inputAlign"
        :error-message-align="errorMessageAlign"
        :autosize="autosize"
        :left-icon="leftIcon"
        :icon-prefix="iconPrefix"
        :rules="editable?rules:null"
        class="ibps-address__street"
      />
    </template>

  </van-cell>
</template>
<script>
import { isDef } from 'vant/lib/utils'
import FieldMixin from '@/mixins/field'
import { getAreaData } from './util/areaData'
import IbpsArea from './area'
import util from './util'

const dataTypeArr = util.dataTypeArr
const levelArr = util.levelArr
let IBPS_AREA_DATA = window.IBPS_AREA_DATA = null

export default {
  name: 'ibps-address',
  components: {
    IbpsArea
  },
  mixins: [FieldMixin],
  props: {
    dataType: { // 数据类型
      type: String,
      default: 'all',
      validator: (value) => {
        return dataTypeArr.indexOf(value) !== -1
      }
    },
    store: { // 返回值类型 stringKey字符串key , array: 数组,string 字符串类型
      type: String,
      default: 'stringKey',
      validator: function(value) {
        return ['array', 'string', 'stringKey'].indexOf(value) !== -1
      }
    },
    storeSeparator: { // 返回值分割符，对于设置字符串类型的分隔符
      type: String,
      default: ','
    },
    separator: { // 展示分割符
      type: String,
      default: '/'
    },
    top: { // 最大区域，可选： country、province、city、district
      type: String,
      default: 'country',
      validator: val => {
        return util.oneOf(val, levelArr)
      }
    },
    topVal: { // 最大区域的值，如top='province'  topVal='CN'
      type: [String, Number],
      default: '0'
    },
    level: { // 最小区域，可选： country、province、city、district
      type: String,
      default: 'district',
      validator: val => {
        return util.oneOf(val, levelArr)
      }
    },
    hasStreet: { // 支持街道
      type: Boolean
    },
    streetPlaceholder: {
      type: String,
      default: '请输入详细地址'
    },
    title: {
      type: String,
      default: '选择地址'
    },
    rightIcon: {
      type: String,
      default: 'location-o'
    }
  },
  data() {
    return {
      areaData: IBPS_AREA_DATA,
      areaValue: [],
      showPopup: false,
      street: ''
    }
  },
  computed: {
    showClear() {
      return this.clearable && this.$utils.isNotEmpty(this.value) && isDef(this.value) && this.editable
    }
  },
  watch: {
    value() {
      this.initData()
      this.validate()
    },
    street() {
      this.$emit('input', this.getStoreValue(this.areaValue))
      this.$emit('change-street', this.street)
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    init() {
      if (this.$utils.isEmpty(IBPS_AREA_DATA)) { // 从服务器加载地址数据
        getAreaData().then((data) => {
          this.areaData = IBPS_AREA_DATA = window.IBPS_AREA_DATA = data
          this.initData()
        })
      } else {
        this.areaData = IBPS_AREA_DATA
        this.initData()
      }
    },
    initData() {
      this.areaValue = this.getArrayValue()
      this.inputValue = this.getInputValue()
      if (this.hasStreet) {
        this.street = this.getStreetValue()
      }
    },
    getArrayValue() {
      if (this.$utils.isEmpty(this.value)) { return [] }
      if (this.store === 'stringKey') {
        try {
          return this.getStringKeyValue(this.$utils.parseData(this.value))
        } catch (error) {
          console.warn(error)
          return []
        }
      } else if (this.store === 'string') {
        try {
          return this.$utils.parseData(this.value)
        } catch (error) {
          console.warn(error)
          return []
        }
      } else {
        return this.value
      }
    },
    getStringKeyValue(v) {
      const topIndex = util.getLevelIndex(this.top)
      const levelIndex = util.getLevelIndex(this.level) + 1
      const res = []
      let supCode = this.topVal// 上一级
      for (let i = topIndex; i < levelIndex; i++) {
        const code = v[util.getLevelKey(i)]
        if (code) {
          res.push({
            code: code,
            name: this.areaData[supCode][code]
          })
          supCode = code
        }
      }
      return res
    },
    getStoreValue(value) {
      if (this.$utils.isEmpty(value)) { return '' }
      if (this.store === 'stringKey') {
        const res = {}
        let i = util.getLevelIndex(this.top)
        value.forEach((v) => {
          res[ util.getLevelKey(i)] = v ? v.code : ''
          i++
        })
        if (this.hasStreet) { res['street'] = this.street }
        return this.$utils.isEmpty(res) ? '' : JSON.stringify(res)
      } else if (this.store === 'string') {
        return value.join(this.storeSeparator)
      } else {
        return value || []
      }
    },
    getInputValue() {
      if (this.$utils.isEmpty(this.areaValue)) { return '' }
      const inputValue = []
      this.areaValue.forEach(v => {
        inputValue.push(v.name)
      })
      return inputValue.join(this.separator)
    },
    getStreetValue() {
      if (this.$utils.isEmpty(this.value)) { return '' }
      if (this.store === 'stringKey') {
        try {
          const v = this.$utils.parseData(this.value)
          return v['street']
        } catch (error) {
          console.warn(error)
          return ''
        }
      }
    },
    onClick() {
      if (!this.editable) { return }
      this.areaValue = this.getArrayValue()
      this.showPopup = true
    },
    onCancel() {
      this.showPopup = false
    },
    onConfirm(data) {
      this.showPopup = false
      this.$emit('input', this.getStoreValue(data))
    },
    onRightIconClick() {
      this.showClear ? this.onClear() : this.onClick()
    },
    onClear() {
      this.$emit('input', this.getStoreValue())
    }
  }
}
</script>
