<template>
  <div class="sv-tabs" :class="{'sv-tabs-bottom': position === 'bottom', 'sv-tabs-top': position === 'top', 'fixed': fixed}">
    <div class="sv-tab-links" ref="svTabLinksRef" :class="tabLinksClass">
      <template v-for="(tab, $index) in tabLinks">
        <button class="sv-tab-link" :class="{'is-active': tab.value === activeTabValue}" @click="handleTabClick(tab)" ref="svTabLinkRef">
          <i class="tab-link-icon" :class="tabLinkIconClass(tab)"></i>
          <span class="tab-link-text">{{tab.title}}</span>
        </button>
      </template>
      <div class="sv-tab-link-highlight" :style="linkHighlightStyle" v-if="stripe"></div>
    </div>
    <div class="sv-tab-contents" ref="svTabContentsRef">
      <div class="sv-tab-panels" :style="tabPanelsStyle" ref="svTabPanelsRef">
        <slot></slot>
      </div>
    </div>
  </div>
</template>

<script type="es6">
  export default {
    name: 'svTabs',
    props: {
      value: {
        type: [String, Number],
        default: 0
      },
      active: {
        type: [String, Number],
        default: 0
      },
      position: {
        type: String,
        default: 'bottom'
      },
      fixed: {
        type: Boolean,
        default: false
      },
      slidable: {
        type: Boolean,
        default: false
      },
      stripe: {
        type: Boolean,
        default: false
      },
      type: {
        type: String,
        default: ''
      },
      bgColor: String,
      color: String,
      iconPosition: {
        type: String,
        default: 'top'
      }
    },
    data () {
      return {
        hasIcon: false,
        activeTabValue: this.value || this.active,
        activeTabIndex: 0,
        tabLinks: [],
        linkHighlightStyle: {
          width: 0,
          transform: 'translateX(0)'
        },
        tabPanelsStyle: {
          transform: 'translateX(0)',
          transition: 'transform 0s'
        },
        tabPanelWidth: document.body.clientWidth,
        direction: '',
        slideDistance: 0,
        translateX: 0,
        threshold: 80, // 切换到下一页的阀值
        translateYList: [] // 保存每一个tab当前滚动的Y轴的距离
      }
    },
    watch: {
      activeTabIndex (val) {
        this.activeTabValue = this.tabLinks[val].value
        this.$emit('input', this.activeTabValue)
      }
    },
    computed: {
      tabLinksClass () {
        let className
        if (this.bgColor) {
          if (this.type === 'button') {
            className += ''
          } else {
            className = `sv-tab-links-bg-${this.bgColor}`
          }
        }
        if (this.color) {
          className += ` sv-tab-links-${this.color}`
        }
        if (this.hasIcon) {
          className += ` has-icon has-${this.iconPosition}-icon`
        }
        if (this.type) {
          className += ` sv-tab-links-${this.type}`
        }
        return className
      }
    },
    methods: {
      tabLinkIconClass (tabLink) {
        if (!tabLink.icon) return ''
        return `sv-icon-${tabLink.icon}`
      },
      handleTabClick (tab) {
        this.activeTabIndex = tab.index
        let translateX = -tab.index * this.tabPanelWidth
        this.translateX = translateX
        this.slideLink(tab.index)
        this.slide(translateX)
        this.$emit('tab-active', tab)
      },
      preventSlide () {
        this.tabPanelsStyle.transform = `translateX(${this.translateX}px)`
      },
      slideLink (activeTabIndex) {
        let activeTabLinkOffsetLeft = this.$refs.svTabLinkRef[activeTabIndex].offsetLeft
        this.linkHighlightStyle.transform = `translateX(${activeTabLinkOffsetLeft}px)`
      },
      slide (translateX, transitionDuration = 0) {
        this.tabPanelsStyle.transition = `transform ${transitionDuration}s`
        this.tabPanelsStyle.transform = `translateX(${translateX}px)`
      },
      renderTabs () {
        let tabs = this.$children

        tabs.forEach((tab, index) => {
          this.tabLinks.push({
            title: tab.title,
            value: tab.value || index,
            icon: tab.icon,
            index
          })

          this.translateYList.push(0) // 初始化每个tab的Y轴滚动的距离为0
        })

        if (this.value) {
          this.activeTabValue = this.value
          this.activeTabIndex = this.tabLinks.filter(tab => {
            return tab.value === this.value
          })[0].index
        }


        for (let i = 0; i < tabs.length; i++) {
          if (tabs[i].icon) {
            this.hasIcon = true
            break
          }
        }

        this.linkHighlightStyle.width = `${(100 / this.tabLinks.length).toFixed(5)}%`
        if (this.fixed) {
          this.tabPanelWidth = document.body.clientWidth
        } else {
          this.tabPanelWidth = this.$refs.svTabLinksRef.clientWidth
        }

        this.$nextTick(() => {
          this.slideLink(this.activeTabIndex)
          let translateX = -(this.activeTabIndex * this.tabPanelWidth)
          this.translateX = translateX
          this.slide(translateX)

          if (this.slidable) {
            this.bindSlideEvents()
          }
        })
      },
      bindSlideEvents () {
        let $tabPanels = this.$refs.svTabPanelsRef
        let startX, currentX, endX, slideDistance
        let startY, currentY, endY
        $tabPanels.addEventListener('touchstart', event => {
          startX = event.touches[0].pageX
          startY = event.touches[0].pageY
        })
        $tabPanels.addEventListener('touchmove', event => {
          currentX = event.touches[0].pageX
          currentY = event.touches[0].pageY

          /*
           纵向位移大于横向位移时，说明用户想进行上下滑动的操作，在此禁掉左右滑动
           否则就会有太过灵敏的感觉（上下滑动时在左右方向上稍微有些位移tab就会左右滑动）
            */
          if (Math.abs(currentY - startY) > Math.abs(currentX - startX)) {
          } else {
            this.direction = currentX < startX ? 'left' : 'right'

            if ((this.direction === 'left' && this.activeTabIndex === this.tabLinks.length - 1) ||
              (this.direction === 'right' && this.activeTabIndex === 0)) {
              this.preventSlide()
            } else {
              this.slide(this.translateX + currentX - startX)
            }
          }
        })

        $tabPanels.addEventListener('touchend', event => {
          endX = event.changedTouches[0].pageX
          slideDistance = endX - startX

          if ((this.direction === 'left' && this.activeTabIndex === this.tabLinks.length - 1) ||
            (this.direction === 'right' && this.activeTabIndex === 0)) {
            this.preventSlide()
          } else {
            let transitionDuration
            if (Math.abs(slideDistance) < this.threshold) {
              transitionDuration = 0.3
            } else {
              if (this.direction === 'left') {
                this.translateX -= this.tabPanelWidth
                this.activeTabIndex += 1
              }
              if (this.direction === 'right') {
                this.translateX += this.tabPanelWidth
                this.activeTabIndex -= 1
              }
              transitionDuration = 0.6
            }
            this.slideLink(this.activeTabIndex)
            this.slide(this.translateX, transitionDuration)
          }
        })
      }
    },
    mounted () {
      this.renderTabs()
      this.$nextTick(() => {
        if (this.fixed) {
          this.$refs.svTabPanelsRef.style.height = document.documentElement.clientHeight - this.$refs.svTabLinksRef.offsetHeight + 'px'
        }
      })
    }
  }
</script>

<style lang="scss" rel="stylesheet/scss">
  @import "../../styles/base";
  .sv-tabs{
    display: flex;
    flex-direction: column;
    &.fixed{
      &.sv-tabs-top{
        padding-top: pxToRem(70);
        .sv-tab-links{
          position: fixed;
          top:0;
          z-index: 1;
          width: 100%;
        }
      }
    }
    &.sv-tabs-bottom{
      flex-direction: column-reverse;
      .sv-tab-links{
        border-top: pxToRem(1) solid #d2d2d2;
        .sv-tab-link-highlight{
          top:0;
        }
      }
    }
    &.sv-tabs-top{
      .sv-tab-links{
        border-bottom: pxToRem(1) solid #d2d2d2;
        .sv-tab-link-highlight{
          bottom:0;
        }
      }
    }
    .sv-tab-links{
      position: relative;
      display: flex;
      height: pxToRem(70);
      font-size: pxToRem(28);
      color:#333;
      background: $color-light;
      &.sv-tab-links-button{
        height: auto;
        border: pxToRem(1) solid #ccc;
        border-radius: pxToRem(50%);
        overflow:hidden;
        background: #fdfdfd;
        .sv-tab-link{
          padding: pxToRem(10 0);
          border-right: pxToRem(1) solid #ccc;
          color:#999;
          &:last-child{
            border-right: none;
          }
          &.is-active{
            background: $color-primary;
            color:#000;
          }
        }
      }
      &.has-icon{
        color:#888;
        &.has-top-icon{
          .sv-tab-link{
            flex-direction: column;
            .tab-link-icon{
              font-size: pxToRem(40);
            }
            .tab-link-text{
              font-size: pxToRem(22);
            }
          }
        }
        &.has-left-icon{
          .sv-tab-link{
            .tab-link-text{
              margin-left: pxToRem(6);
            }
            .tab-link-icon{
              font-size: pxToRem(32);
            }
          }
        }
        &.has-right-icon{
          .sv-tab-link{
            flex-direction: row-reverse;
            .tab-link-text{
              margin-right: pxToRem(6);
            }

          }
        }
        .sv-tab-link{
          display: flex;
          justify-content: center;
          align-items: center;
          .tab-link-icon{
            font-size: pxToRem(40);
          }
        }
      }
      &.sv-tab-links-bg-light{
        background: $color-light;
        .sv-tab-link{
          &.is-active{
            color:$color-light;
          }
        }
        .sv-tab-link-highlight{
          background: $color-light;
        }
      }
      &.sv-tab-links-bg-stable{
        background: $color-stable;
        .sv-tab-link{
          &.is-active{
            color:$color-stable;
          }
        }
        .sv-tab-link-highlight{
          background: $color-stable;
        }
      }
      &.sv-tab-links-bg-primary{
        background: $color-primary;
        .sv-tab-link{
          &.is-active{
            color:$color-primary;
          }
        }
        .sv-tab-link-highlight{
          background: $color-primary;
        }
      }
      &.sv-tab-links-bg-danger{
        background: $color-danger;
        .sv-tab-link{
          &.is-active{
            color:$color-light;
          }
        }
        .sv-tab-link-highlight{
          background: $color-light;
        }
      }
      &.sv-tab-links-light{
        .sv-tab-link{
          &.is-active{
            color:$color-light;
          }
        }
        .sv-tab-link-highlight{
          background: $color-light;
        }
      }
      &.sv-tab-links-stable{
        .sv-tab-link{
          &.is-active{
            color:$color-stable;
          }
        }
        .sv-tab-link-highlight{
          background: $color-stable;
        }
      }
      &.sv-tab-links-primary{
        .sv-tab-link{
          &.is-active{
            color:$color-primary;
          }
        }
        .sv-tab-link-highlight{
          background: $color-primary;
        }
      }
      &.sv-tab-links-info{
        .sv-tab-link{
          &.is-active{
            color: $color-info;
          }
        }
        .sv-tab-link-highlight{
          background: $color-info;
        }
      }
      &.sv-tab-links-success{
        .sv-tab-link{
          &.is-active{
            color:$color-success;
          }
        }
        .sv-tab-link-highlight{
          background: $color-success;
        }
      }
      &.sv-tab-links-danger{
        .sv-tab-link{
          &.is-active{
            color:$color-danger;
          }
        }
        .sv-tab-link-highlight{
          background: $color-danger;
        }
      }
      &.sv-tab-links-warning{
        .sv-tab-link{
          &.is-active{
            color:$color-warning;
          }
        }
        .sv-tab-link-highlight{
          background: $color-warning;
        }
      }
      .sv-tab-link{
        flex: 1;
        border:none;
        outline: none;
        margin:0;
        padding:0;
        background: transparent;
        &.is-active{
          color: $color-lively;
        }
      }
      .sv-tab-link-highlight{
        position: absolute;
        left:0;
        height: pxToRem(1);
        background:$color-lively;
        transition: transform .4s ease-out;
      }
    }
    .sv-tab-contents{
      font-size: pxToRem(28);
      overflow: hidden;
      .sv-tab-panels{
        display: flex;
        align-items: flex-start;
        transition: transform .2s;
        .sv-tab{
          flex-shrink: 0;
          width: 100%;
          height: 100%;
          overflow: auto;
        }
      }
    }
  }
</style>
