<template>
  <!-- 打开选择器按钮图标 -->
  <image
    :class="classList"
    :style="imgStyle"
    :src="imgIcon"
  />
  <template v-if="showPicker">
    <view
      class="animation-element-wrapper"
      :style="'visibility:' + (show ? 'visible':'hidden')"
      @tap.stop="cancel"
    >
      <view
        class="animation-element"
        @tap.stop="nono"
      >
        <text
          class="right-bt"
          @tap.stop="hiddenFloatView"
        >
          确定
        </text>
        <view class="line" />
        <picker-view
          indicator-style="height: 70rpx;"
          :value="addressValue"
          @change="bindChange"
          @tap.stop="nono"
        >
          <!--省-->
          <picker-view-column>
            <view
              v-for="(item, i) in provArray"
              :key="i"
            >
              {{ item.areaName }}
            </view>
          </picker-view-column>
          <!--地级市-->
          <picker-view-column>
            <view
              v-for="(item, i) in cityArray"
              :key="i"
            >
              {{ item.areaName }}
            </view>
          </picker-view-column>
          <!--区县-->
          <picker-view-column>
            <view
              v-for="(item, i) in areaArray"
              :key="i"
            >
              {{ item.areaName }}
            </view>
          </picker-view-column>
        </picker-view>
      </view>
    </view>
  </template>
</template>

<script setup>
import icon from '@/static/images/icon/more.png'
import http from '@/utils/http'

const props = defineProps({
  // 获取父组件传递过来的省市区数据，统一格式为[省areaId, 市areaId, 区areaId]
  value: {
    type: Array,
    default: () => {
      return []
    }
  },
  // 样式类数组
  classList: {
    type: Array,
    default: () => {
      return []
    }
  },
  // 自定义样式
  imgStyle: {
    type: Object,
    default: () => {
      return {}
    }
  },
  // 选择器图标，可以自行更换，需传入图标路径
  imgIcon: {
    type: String,
    default: icon
  },
  // 控制选择器显隐
  showPicker: {
    type: Boolean,
    default: false
  }
})

/**
 * 定义所需要操作父组件的数据
 * change: 数据发生改变时，给父组件返回数据
 * showPicker: 改变父组件的值，从而可以在子组件进行关闭选择器
 * value: 用做与父组件数据同步的值
 */
const emit = defineEmits(['change', 'update:showPicker', 'update:value'])

// 当数据发生改变时，返回结果给父组件
// eslint-disable-next-line no-unused-vars
const change = (arr) => {
  emit('change', arr)
}

// 监听showPicker的改变，控制选择器显隐
watch(() => props.showPicker, (newVal) => {
  show.value = !!newVal
})

// 监听value的改变，重新给选择器赋值
watch(() => props.value, async (newVal) => {
  if (newVal.length >= 3) {
    if (provArray.value.length > 0) {
      await getCityArray(newVal[0], newVal[1], newVal[2])
    }
  } else {
    addressValue.value = [0, 0, 0]
    await getCityArray(provArray.value[0].areaId)
  }
})

// 获取地址列表
const getAreaListInfo = () => {
  return new Promise((resolve) => {
    http.request({
      url: '/mall4cloud_order/area/list',
      method: 'GET',
      data: {}
    }).then(res => {
      resolve(res)
    })
  })
}

const addressValue = ref([])
const provArray = ref([])
onLoad(async () => {
  // 获取地址列表信息
  const res = await getAreaListInfo()
  if (res.data.length > 0) {
    provArray.value = res.data
  }
  if (props.value.length >= 3) {
    await getCityArray(props.value[0], props.value[1], props.value[2])
  } else {
    addressValue.value = [0, 0, 0]
    await getCityArray(provArray.value[0].areaId)
  }
})

const cityArray = ref([])
const areaArray = ref([])
let addressIndex = []
// 滑动事件
const bindChange = (e) => {
  const val = e.detail.value // 判断滑动的是第几个column
  // 若省份column做了滑动则定位到地级市和区县第一位
  if (addressIndex[0] !== val[0]) {
    val[1] = 0
    val[2] = 0 // 更新数据
    getCityArray(provArray.value[val[0]].areaId) // 获取地级市数据
  } else {
    // 若省份column未做滑动，地级市做了滑动则定位区县第一位
    if (addressIndex[1] !== val[1]) {
      val[2] = 0 // 更新数据
      getAreaArray(cityArray.value[val[1]].areaId) // 获取区县数据
    }
  }
  if (addressIndex[0] !== val[0] || addressIndex[1] !== val[1] || addressIndex[2] !== val[2]) {
    addressValue.value = [val[0], val[1], val[2]]
    addressIndex = addressValue.value
  }
}

// 获取当前节点下的地址
const getCurrentAreas = (curList, curId) => {
  if (curId) {
    for (let index = 0; index < curList.length; index++) {
      if (curList[index].areaId === curId) {
        return {
          curNode: curList[index],
          areas: curList[index].areas,
          index
        }
      }
    }
  } else {
    const one = curList[0]
    return {
      curNode: one,
      areas: one.areas,
      index: 0
    }
  }
}

// 获取当前id下的地址信息
const listAreaByParentId = (pid) => {
  let paramData = {}
  if (!pid) {
    paramData = { level: 1 }
  } else {
    paramData = { pid }
  }
  return new Promise((resolve) => {
    http.request({
      url: '/p/area/listByPid',
      method: 'GET',
      data: paramData
    }).then(res => {
      resolve(res)
    })
  })
}

/**
 * 根据省份ID获取 城市数据
 */
const getCityArray = async (provId, cityId, areaId) => {
  const { curNode, areas, index } = getCurrentAreas(provArray.value, provId)
  let cityArr = areas
  if (!areas) {
    listAreaByParentId(provId).then(res => {
      if (res.data.length > 0) {
        cityArr = res.data
      }
    })
  }
  if (curNode) {
    curNode.areas = cityArr
  }
  if (index) {
    addressValue.value = [index, 0, 0]
  }
  cityArray.value = cityArr

  if (cityId) {
    for (let i = 0; i < cityArray.value.length; i++) {
      if (cityArray.value[i].areaId === cityId) {
        addressValue.value = [addressValue.value[0], i, addressValue.value[2]]
      }
    }
  }

  await getAreaArray(cityId || cityArray.value[0].areaId, areaId)
}

/**
 * 根据城市ID获取 区数据
 */
const getAreaArray = async (cityOfId, areaOfId) => {
  const { curNode, areas, index } = getCurrentAreas(cityArray.value, cityOfId)
  let areaArr = areas
  if (!areas) {
    listAreaByParentId(cityOfId).then(res => {
      if (res.data.length > 0) {
        areaArr = res.data
      }
    })
  }
  if (index) {
    addressValue.value = [addressValue.value[0], index, 0]
  }
  curNode.areas = areaArr
  areaArray.value = areaArr
  if (areaOfId) {
    for (let index = 0; index < areaArray.value.length; index++) {
      if (areaArray.value[index].areaId === areaOfId) {
        addressValue.value = [addressValue.value[0], addressValue.value[1], Number(index)]
      }
    }

    addressIndex = addressValue.value
  }
}

const show = ref(false)
/**
 * 隐藏弹窗浮层，并重新赋值
 */
const hiddenFloatView = () => {
  emit('update:showPicker', false)
  initCityData(addressValue.value[0], addressValue.value[1], addressValue.value[2])
}

/**
 * 仅取消浮窗，不改变值
 */
const cancel = async () => {
  await getCityArray(props.value[0], props.value[1], props.value[2])
  emit('update:showPicker', false)
}

// 返回地区id及地区名称
const initCityData = async (provId, cityId, areaId) => {
  const arr = [{
    areaId: provArray.value[provId].areaId,
    areaName: provArray.value[provId].areaName
  }, {
    areaId: cityArray.value[cityId].areaId,
    areaName: cityArray.value[cityId].areaName
  }, {
    areaId: areaArray.value[areaId].areaId,
    areaName: areaArray.value[areaId].areaName
  }]
  emit('update:value', [arr[0].areaId, arr[1].areaId, arr[2].areaId])
  emit('change', arr)
}

// 空方法
const nono = () => {}

</script>
<style scoped lang="scss">
picker-view {
  background-color: white;
  padding: 0;
  width: 100%;
  height: 380rpx;
  bottom: 0;
  position: fixed;
  text {
    color: #999;
    display: inline-flex;
    position: fixed;
    margin-top: 20rpx;
    height: 50rpx;
    text-align: center;
    line-height: 50rpx;
    font-size: 34rpx;
    font-family: Arial, Helvetica, sans-serif;
  }
}
picker-view-column {
  view {
    vertical-align: middle;
    font-size: 30rpx;
    line-height: 30rpx;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}
.animation-element-wrapper {
  display: flex;
  position: fixed;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  background-color: rgba(0, 0, 0, 0.6);
  z-index: 999;
}
.animation-element {
  display: flex;
  position: fixed;
  width: 100%;
  height: 530rpx;
  bottom: 0;
  background-color: rgba(255, 255, 255, 1);
}

.right-bt {
  right: 35rpx;
  top: 20rpx;
  position: absolute;
  width: 80rpx !important;
}
.line {
  display: block;
  position: fixed;
  height: 2rpx;
  width: 100%;
  margin-top: 89rpx;
  background-color: #eee;
}
</style>
