<template>
  <section class="AiAreaSelect">
    <el-row type="flex" :gutter="5">
      <el-col v-for="(item,i) in areaInfo" :key="i" v-show="isShowSelector(i)" style="width: auto;">
        <el-select :size="selectClass" v-if="areaLists[i].length>0||alwaysShow" @focus="$emit('focus')"
                   @blur="$emit('blur')" :placeholder="placeVal[i]" clearable
                   :disabled="isDisabledSelector(i)" :value="areaInfo[i]" @change="v=>handleSelectorChange(v,i)">
          <template v-if="lockFirstOption&&i==(hideNum||0)">
            <el-option v-if="!areaInfo[i]||areaInfo[i]===area.id" v-for="(area,j) in areaLists[i]" :key="j"
                       :value="area.id" :label="area.name"/>
          </template>
          <el-option v-else v-for="(area,j) in areaLists[i]" :key="j" :value="area.id" :label="area.name"/>
        </el-select>
      </el-col>
    </el-row>
  </section>
</template>

<script>
export default {
  name: "AiAreaSelect",
  model: {
    prop: 'value',
    event: 'change',
  },
  inject: {
    elFormItem: {default: ""},
  },
  props: {
    value: String,
    areaLevel: {type: [Number, String], default: 5},
    disabledLevel: {type: [Number, String], default: 0},
    disabled: {type: Boolean, default: false},
    hideLevel: {type: [Number, String], default: 0},
    valueLevel: {type: [Number, String], default: -1},
    alwaysShow: {type: Boolean, default: false},
    selectClass: {type: String, default: 'small'},
    lockFirstOption: {type: Boolean, default: false},
    instance: Function,
    action: String,
    provinceAction: String
  },
  computed: {
    hideNum() {
      return Number(this.hideLevel)
    },
    disabledNum() {
      return Number(this.disabledLevel)
    },
    showNum() {
      return Number(this.areaLevel)
    },
    valueIndex() {
      return Number(this.valueLevel)
    },
    current() {
      return this.selected || this.value
    },
    areaInfo() {
      let info = {}
      const currentLevel = this.getLevelByAreaId(this.current)
      for (let i = 0; i < this.showNum; i++) {
        //防止地区代码出现,在获取到选项后再赋值
        if (i <= currentLevel) info[i] = this.areaLists[i]?.length ? this.getAreaByAreaType(i) : ""
        else info[i] = null
      }
      return info
    },
    areaObj() {
      let info = {}
      for (let key in this.areaInfo) {
        if (this.areaInfo[key]) {
          info[key] = this.areaLists[key].find(e => e.id === this.areaInfo[key])
        }
      }
      return info
    },
    selectedName() {
      const index = this.getLevelByAreaId(this.current)
      if (index > -1) {
        const area = this.areaLists[index].find(e => e.id === this.current)
        return area ? area.name : ""
      } else return ""
    },
    selectedFullName() {
      let name = ""
      for (let i in this.areaInfo) {
        if (this.areaInfo[i]) {
          const area = this.areaLists[i].find(e => e.id === this.areaInfo[i])
          name += area ? area.name : ""
        }
      }
      return name
    },
    areaLelve() {
      return this.getLevelByAreaId(this.current);
    }
  },
  watch: {
    selected() {
      if (this.valueIndex > -1) {
        this.$emit("change", this.areaInfo[this.valueIndex] || null)
      } else {
        this.$emit("change", this.current)
      }
      this.$emit("area", this.areaInfo);
      this.$emit('areaLelve', this.areaLelve)
    },
    areaObj() {
      this.$emit("areaObj", this.areaObj)
    },
    selectedName() {
      this.$emit("name", this.selectedName)
    },
    selectedFullName() {
      this.$emit("fullname", this.selectedFullName)
    },
    valueLevel() {
      this.refreshAreaList();
    },
    value(v) {
      //特殊处置结果 后台传值赋值改变需要重新加载数据
      this.dispatch('ElFormItem', 'el.form.change', [v]);
      if (!this.selected) {
        this.refreshAreaList();
      }
    }
  },
  data() {
    return {
      selected: null,
      areaLists: {
        0: [],
        1: [],
        2: [],
        3: [],
        4: [],
      },
      placeVal: {
        0: '请选择省',
        1: '请选择市',
        2: '请选择区',
        3: '请选择镇',
        4: '请选择村'
      },
      ProvinceCityCounty: []
    }
  },
  methods: {
    isShowSelector(i) {
      let index = Number(i)
      return index >= this.hideNum
    },
    isDisabledSelector(i) {
      let index = Number(i)
      return this.disabled || (index < this.disabledNum)
    },
    handleSelectorChange(area, index) {
      if (area) {
        this.selected = area
        if (index < 4 && this.areaInfo[index]) {
          this.getAreasByParentId(index).then(() => {
            for (let i = index; i < this.showNum; i++) {
              if (this.areaLists[i + 2]) this.areaLists[i + 2] = []
            }
          })
        }
      } else {//清空操作
        let i = Number(index), pre = i - 1, origin = JSON.parse(JSON.stringify(this.areaInfo))
        if (pre > 0) {
          this.selected = origin[pre]
          for (let j = i + 1; j < this.showNum; j++) {
            this.areaLists[j] = []
          }
        } else {
          this.selected = origin[0]
          for (let j = i + 2; j < this.showNum; j++) {
            this.areaLists[j] = []
          }
        }
      }
    },
    getAreasByParentId(index) {
      index = Number(index)
      return new Promise((resolve) => {
        this.areaLists[index + 1] = []
        if (index < 2) {
          index = Number(index)
          let data = this.ProvinceCityCounty.filter(e => e.parentId == this.areaInfo[index])
          if (data && (index + 1 < this.showNum)) this.areaLists[index + 1] = data
          this.$forceUpdate();
          resolve(index)
        } else {
          this.instance.post(this.action || "/admin/area/queryAreaByParentId", null, {
            withoutToken: true,
            params: {id: this.areaInfo[index]}
          }).then(res => {
            if (res?.data) {
              index = Number(index)
              if (index + 1 < this.showNum) this.areaLists[index + 1] = res.data
              this.$forceUpdate()
            }
            resolve(index)
          })
        }

      })
    },
    getProvinceCityCounty() {
      return this.instance.post(this.provinceAction || "/admin/area/queryProvinceListContainCity", null, {withoutToken: true})
    },
    getAreaByAreaType(areaType) {
      let lvCount = [2, 4, 6, 9, 12]
      return this.current?.split("").map((e, i) => i < lvCount[areaType] ? e : 0).join("")
    },
    getLevelByAreaId(code) {
      if (code) {
        if (code.length == 2 || code.endsWith('0000000000')) return 0
        else if (code.endsWith('00000000')) return 1
        else if (code.endsWith('000000')) return 2
        else if (code.endsWith('000')) return 3
        else return 4
      } else return -1
    },
    refreshAreaList() {
      for (let i = 0; i < this.showNum; i++) {
        this.areaLists[i] = []
      }
      this.getProvinceCityCounty().then(res => {
        this.ProvinceCityCounty = res.data
        this.areaLists[0] = res.data.filter(d => !d.parentId)
        const getAreaList = i => {
          if (this.areaInfo?.[i])
            this.getAreasByParentId(i).then(next => getAreaList(next + 1))
        }
        getAreaList(0)
      })
    },
    /**
     * 表单验证
     * @param componentName
     * @param eventName
     * @param params
     */
    dispatch(componentName, eventName, params) {
      let parent = this.$parent || this.$root;
      let name = parent.$options.componentName;

      while (parent && (!name || name !== componentName)) {
        parent = parent.$parent;

        if (parent) {
          name = parent.$options.componentName;
        }
      }
      if (parent) {
        parent.$emit.apply(parent, [eventName].concat(params));
      }
    },
  },
  created() {
    this.refreshAreaList()
  }
}
</script>

<style lang="scss" scoped>
.AiAreaSelect {
  .el-col {
    min-width: 90px;
  }
}
</style>
