<template>
  <admin-layout>
    <contextmenu :itemList="menuItemList" :visible.sync="menuVisible" @select="onMenuSelect" />
    <a-tabs
      v-if="multiPage"
      type="editable-card"
      :active-key="activePage"
      :style="`margin: -16px auto 8px; ${layout == 'head' && pageWidth == 'fixed' ? 'max-width: 1400px;' : ''}`"
      :hide-add="true"
      @change="changePage"
      @edit="editPage"
      @contextmenu="onContextmenu"
    >
      <a-tab-pane :key="page.fullPath" v-for="page in pageList">
        <span slot="tab" :pagekey="page.fullPath">{{pageName(page)}}</span>
      </a-tab-pane>
    </a-tabs>
    <div class="tabs-view-content" :style="`margin-top: ${multiPage ? -24 : 0}px`">
      <page-toggle-transition :disabled="animate.disabled" :animate="animate.name" :direction="animate.direction">
        <a-keep-alive v-if="multiPage" v-model="clearCaches">
          <router-view ref="tabContent" :key="$route.fullPath" />
        </a-keep-alive>
        <router-view v-else />
      </page-toggle-transition>
    </div>
  </admin-layout>
</template>

<script>
import AdminLayout from '@/layouts/AdminLayout'
import Contextmenu from '@/components/menu/Contextmenu'
import PageToggleTransition from '@/components/transition/PageToggleTransition'
import {mapState, mapMutations} from 'vuex'
import {getI18nKey} from '@/utils/routerUtil'
import AKeepAlive from '@/components/cache/AKeepAlive'

export default {
  name: 'TabsView',
  i18n: require('./i18n'),
  components: { PageToggleTransition, Contextmenu, AdminLayout , AKeepAlive },
  data () {
    return {
      clearCaches: [],
      pageList: [],
      cachedKeys: [],
      activePage: '',
      menuVisible: false
    }
  },
  computed: {
    ...mapState('setting', ['multiPage', 'animate', 'layout', 'pageWidth']),
    menuItemList() {
      return [
        { key: '1', icon: 'vertical-right', text: this.$t('closeLeft') },
        { key: '2', icon: 'vertical-left', text: this.$t('closeRight') },
        { key: '3', icon: 'close', text: this.$t('closeOthers') }
      ]
    },
    tabsOffset() {
      return this.multiPage ? 24 : 0
    }
  },
  created () {
    const route = this.$route
    this.pageList.push(route)
    this.activePage = route.fullPath
    if (this.multiPage) {
      window.addEventListener('page:close', this.closePageListener)
    }
  },
  mounted () {
    this.correctPageMinHeight(-this.tabsOffset)
    if(this.multiPage){
      this.cachedKeys.push(this.$refs.tabContent.$vnode.key)
    }
  },
  beforeDestroy() {
    window.removeEventListener('page:close', this.closePageListener)
    this.correctPageMinHeight(this.tabsOffset)
  },
  watch: {
    '$route': function (newRoute) {
      this.activePage = newRoute.fullPath
      if (!this.multiPage) {
        this.pageList = [newRoute]
      } else if (this.pageList.findIndex(item => item.fullPath == newRoute.fullPath) == -1) {
        this.$nextTick(() => {
          this.cachedKeys.push(this.$refs.tabContent.$vnode.key)
        })
        this.pageList.push(newRoute)
      }
    },
    'multiPage': function (newVal) {
      if (!newVal) {
        this.pageList = [this.$route]
        window.removeEventListener('page:close', this.closePageListener)
      } else {
        window.addEventListener('page:close', this.closePageListener)
      }
    },
    tabsOffset(newVal, oldVal) {
      this.correctPageMinHeight(oldVal - newVal)
    }
  },
  methods: {
    changePage (key) {
      this.activePage = key
      this.$router.push(key)
    },
    editPage (key, action) {
      this[action](key) // remove
    },
    remove (key, next) {
      if (this.pageList.length === 1) {
        return this.$message.warning(this.$t('warn'))
      }
      let index = this.pageList.findIndex(item => item.fullPath === key)
      //清除缓存
      this.clearCaches = this.cachedKeys.splice(index, 1)
      this.pageList.splice(index, 1)
      if (next) {
        this.$router.push(next)
      } else if (key === this.activePage) {
        index = index >= this.pageList.length ? this.pageList.length - 1 : index
        this.activePage = this.pageList[index].fullPath
        this.$router.push(this.activePage)
      }
    },
    onContextmenu (e) {
      const pageKey = getPageKey(e.target)
      if (pageKey) {
        e.preventDefault()
        this.menuVisible = true
      }
    },
    onMenuSelect (key, target) {
      let pageKey = getPageKey(target)
      switch (key) {
        case '1': this.closeLeft(pageKey); break
        case '2': this.closeRight(pageKey); break
        case '3': this.closeOthers(pageKey); break
        default: break
      }
    },
    closeOthers (pageKey) {
      const index = this.pageList.findIndex(item => item.fullPath === pageKey)
      // 清除缓存
      this.clearCaches = this.cachedKeys.filter((item, i) => i != index)
      this.cachedKeys = this.cachedKeys.slice(index, index + 1)

      this.pageList = this.pageList.slice(index, index + 1)
      if (this.activePage != pageKey) {
        this.activePage = pageKey
        this.$router.push(this.activePage)
      }
    },
    closeLeft (pageKey) {
      const index = this.pageList.findIndex(item => item.fullPath === pageKey)
      // 清除缓存
      this.clearCaches = this.cachedKeys.filter((item, i) => i < index)
      this.cachedKeys = this.cachedKeys.slice(index)

      this.pageList = this.pageList.slice(index)
      if (!this.pageList.find(item => item.fullPath === this.activePage)) {
        this.activePage = pageKey
        this.$router.push(this.activePage)
      }
    },
    closeRight (pageKey) {
      const index = this.pageList.findIndex(item => item.fullPath === pageKey)
      // 清除缓存
      this.clearCaches = this.cachedKeys.filter((item, i) => i > index)
      this.cachedKeys = this.cachedKeys.slice(0, index+1)

      this.pageList = this.pageList.slice(0, index + 1)
      if (!this.pageList.find(item => item.fullPath === this.activePage)) {
        this.activePage = pageKey
        this.$router.push(this.activePage)
      }
    },
    pageName(page) {
      return this.$t(getI18nKey(page.matched[page.matched.length - 1].path))
    },
    closePageListener(event) {
      const {closeRoute, nextRoute} = event.detail
      const closePath = typeof closeRoute === 'string' ? closeRoute : closeRoute.path
      this.remove(closePath, nextRoute)
    },
    ...mapMutations('setting', ['correctPageMinHeight'])
  }
}
/**
 * 由于ant-design-vue组件库的TabPane组件暂不支持自定义监听器，无法直接获取到右键target所在标签页的 pagekey 。故增加此方法用于
 * 查询右键target所在标签页的标识 pagekey ，以用于自定义右键菜单的事件处理。
 * 注：TabPane组件支持自定义监听器后可去除该方法并重构 ‘自定义右键菜单的事件处理’
 * @param target 查询开始目标
 * @param depth 查询层级深度 （查找层级最多不超过3层，超过3层深度直接返回 null）
 * @returns {String}
 */
function getPageKey (target, depth = 0) {
  if (depth > 2 || !target) {
    return null
  }
  return target.getAttribute('pagekey') || getPageKey(target.firstElementChild, ++depth)
}
</script>

<style scoped lang="less">
  .tabs-view-content{
    position: relative;
  }
</style>
