<template>
  <div class="ht-tabs">
    <el-tabs
      v-if="!isMobile"
      ref="tabs"
      v-model="val"
      :tab-position="tabPosition"
      :before-leave="beforeLeaveTab"
      :type="type"
      :active-name="activeName"
      :closable="closable"
      :addable="addable"
      :editable="editable"
      :stretch="stretch"
      @tab-click="tabClickHandle"
      @tab-remove="tabRemoveHandle"
      @tab-add="tabAddHandle"
      @edit="tabEditHandle"
    >
      <slot></slot>
    </el-tabs>
    <van-tabs
      v-else
      ref="tabs"
      v-model="val"
      :type="type == 'card' || type == 'border-card' ? 'card' : 'line'"
      :title-active-color="
        type == 'card' || type == 'border-card' ? '#fff' : '#409EFF'
      "
      color="#409EFF"
      class="mobile-tabs"
      :class="{ 'hide-tabs': !isShowTabs }"
      :ellipsis="false"
      :before-change="beforeLeaveTab"
      @click="tabClickHandle"
    >
      <slot></slot>
    </van-tabs>
  </div>
</template>

<script>
  import regionValidator from '@/mixins/regionValidator.js'
  import mobileMode from '@/mixins/mobileMode.js'

  export default {
    name: 'HtTabs',
    mixins: [regionValidator, mobileMode],
    props: {
      tabsValue: String,
      type: String,
      activeName: String,
      beforeLeave: Function,
      closable: {
        type: Boolean,
        default: false,
      },
      addable: {
        type: Boolean,
        default: false,
      },
      editable: {
        type: Boolean,
        default: false,
      },
      tabPosition: {
        type: String,
        default: 'top',
      },
      stretch: {
        type: Boolean,
        default: false,
      },
      isVerify: {
        type: Boolean,
        default: false,
      },
    },
    data() {
      return {
        val: this.tabsValue,
        isShowTabs: true,
      }
    },
    mounted() {
      let me_ = this
      this.$refs.tabs.$watch('panes', function () {
        me_.val = me_.getShowPanes(me_.val)
      })
      this.initVal()
      setTimeout(() => {
        // 解决vant-tab组件官方问题：底部条位置错误
        this.isMobile && this.resize()
      }, 10)
    },
    updated() {
      if (this.$slots.default) {
        this.isShowTabs = this.$slots.default.some(
          (item) => item.tag && item.tag.includes('van-tab')
        )
      }
    },
    methods: {
      // 有些tab如果初始化被隐藏的话，需要默认赋值当前显示的第一个tab
      initVal() {
        if (this.isMobile) {
          return
        }
        let firstTabName = ''
        if (this.$slots.default) {
          this.$slots.default.forEach((k) => {
            if (
              !firstTabName &&
              k.componentOptions &&
              k.componentOptions.propsData &&
              k.componentOptions.propsData.name
            ) {
              firstTabName = k.componentOptions.propsData.name
            }
          })
        }
        let valIndex = this.$slots.default.findIndex((k) => {
          return (
            k.componentOptions &&
            k.componentOptions.propsData &&
            k.componentOptions.propsData.name &&
            k.componentOptions.propsData.name == this.val
          )
        })
        if (firstTabName && valIndex === -1) {
          this.val = firstTabName
        }
      },
      beforeLeaveTab(activeName, oldActiveName) {
        // 切换tab时是否校验
        if (this.isVerify) {
          return new Promise((resolve, reject) => {
            // 应用侧绑定了前置处理方法
            if (this.beforeLeave) {
              const result = this.beforeLeave(activeName, oldActiveName)
              // 应用侧的前置处理方法返回了拒绝切换的结果时 直接 驳回切换操作
              if (result && result.constructor == Promise) {
                result.catch(() => reject())
              } else if (
                result != null &&
                result != undefined &&
                result === false
              ) {
                reject()
              }
            }
            // 执行校验逻辑
            this.validateRegion('.el-tab-pane:not([aria-hidden])').then(
              (errorItems) => {
                if (errorItems.length > 0) {
                  reject()
                } else {
                  resolve()
                }
              }
            )
          })
        } else {
          // 不校验时直接 应用侧的结果 或 直接返回true
          return this.beforeLeave
            ? this.beforeLeave(activeName, oldActiveName)
            : true
        }
      },
      getShowPanes(key) {
        let panes = this.$refs.tabs.panes
        let name = ''
        let flag = false
        for (let i = 0; i < panes.length; i++) {
          if (panes[i].name == key) {
            flag = true
          }
          if (panes[i].$attrs.isShow && !name) {
            name = panes[i].name
          }
        }
        if (flag) {
          return key
        } else {
          return name
        }
      },
      tabClickHandle(tab) {
        this.$root.$emit('tab-click', tab)
      },
      tabRemoveHandle(tabName) {
        this.$emit('tab-remove', tabName)
      },
      tabAddHandle() {
        this.$emit('tab-add')
      },
      tabEditHandle(targetName, action) {
        this.$emit('edit', targetName, action)
      },
      resize() {
        // tabs上面有着resize方法，调用这个方法进行重绘，来解决下划线位置问题
        this.$refs.tabs && this.$refs.tabs.resize()
      },
    },
  }
</script>
<style lang="scss" scoped>
  .ht-tabs {
    ::v-deep {
      .el-tabs__content {
        &:empty {
          display: none;
        }
      }
      .van-tabs.van-tabs--line {
        .van-tabs__wrap {
          border-bottom: 0.5px solid #eee;
        }
        .van-tabs__line {
          &:empty {
            display: none;
          }
        }
      }
      .mobile-tabs {
        margin-bottom: 0;
        div[role='tab'] + .van-tabs__line {
          &:empty {
            display: block;
          }
        }
        .van-tabs__content {
          padding-bottom: 10px;
          border-bottom: 10px solid #f6f6f6;
          &:empty {
            display: none;
          }
        }
      }
      .hide-tabs {
        .van-tabs__wrap {
          display: none;
        }
      }
    }
  }
  .ht-tabs:has(.el-tabs__content:not(:has(*))) {
    display: none;
  }
  .ht-tabs:has(.el-tabs__content:empty) {
    display: none;
  }

  .ht-tabs {
    display: block;
  }
</style>
