<template>
  <view class="wk-dropdown">
    <view class="wk-dropdown-menu">
      <template v-for="(menu, index) in menuList">
        <view
          :key="index"
          :class="{ active: activeMenuIndex === index }"
          :style="{ 
            color: activeMenuIndex === index ? activeColor : inactiveColor
          }"
          class="wk-dropdown-menu_item"
          @tap="handleMenuClick(index)">
          <text :class="menu.leftIcon" class="wk wk-dropdown-menu_item__left-icon" />
          <text class="wk-dropdown-menu_item__text">
            {{ menu.name }}
          </text>
          <text v-if="!menu.leftIcon" class="wk wk-arrow-right wk-dropdown-menu_item__icon" />
        </view>
      </template>
    </view>
		
    <view
      :style="{
        height: contentStyle.height + 'px',
        zIndex: contentStyle.zIndex
      }"
      class="wk-dropdown-content">
      <view
        :style="{
          transform: activeMenuIndex !== -1 ? 'translateY(0)' : 'translateY(-100%)',
          maxHeight: contentHeight * 0.75 + 'px'
        }"
        class="wk-dropdown-content__pop" @click.stop>
        <slot />
      </view>
      <view
        :style="{
          height: maskStyle.height,
          top: maskStyle.top,
          opacity: maskStyle.opacity,
          zIndex: maskStyle.zIndex
        }"
        class="wk-dropdown-content__mask"
        @tap.stop.prevent="handleMenuClick(-1)" />
    </view>
  </view>
</template>

<script>
	/**
	 * WkDropdown 下拉菜单（配合 WkDropdownItem 使用）
	 * @author yxk
	 * @property {String} activeColor 标题和选项卡选中的颜色（默认#3C80F7）
	 * @property {String} inactiveColor 标题和选项卡未选中的颜色（默认#666666）
	 * @property {Boolean} autoClose  DropdownItem为非自定义内容时选择选项后是否自动关闭（默认 false 不自动关闭）
	 * @property {Function} beforeOpen 拦截下拉菜单打开 参数: index next
	 * @event {Function} open 下拉菜单被打开时触发 参数: index
	 * @event {Function} change 切换下拉菜单时触发 参数: index
	 * @event {Function} close 下拉菜单全部被关闭时触发
	 * 
	 * @tips: 关闭下拉选项需手动调用 close 方法
	 * 
	 * @example 
	 *  <wk-dropdown>
	 *    <wk-dropdown-item name="排序" :options="[]"></wk-dropdown-item>
	 *    <wk-dropdown-item name="自定义内容">
	 *      your slot content
	 *    </wk-dropdown-item>
	 *  </wk-dropdown>
	 */
  export default {
    name: 'WkDropdown',
    provide() {
      return {
        dropdown: this
      }
    },
    props: {
      activeColor: {
        type: String,
        default: '#3C80F7'
      },
      inactiveColor: {
        type: String,
        default: '#666666'
      },
      beforeOpen: {
        type: Function,
        default: null
      },
      autoClose: {
        type: Boolean,
        default: false
      }
    },
    data() {
      return {
        activeMenuIndex: -1,
        menuList: [], // 菜单项

        contentStyle: {
          height: 0,
          zIndex: -1
        },
        contentHeight: 0,
        maskStyle: {
          height: 0,
          top: 0,
          opacity: 0,
          zIndex: 1
        },
				
        children: []
      }
    },
    created() {
      this.children = []
    },
    mounted() {
      this.$nextTick(() => {
        this.getContentHeight()
      })
      // console.log(this.children)
      // this.initTab()
    },
    methods: {
      /**
       * 点击menu
       * @param {Number} index
       */
      handleMenuClick(index) {
        if (this.beforeOpen) {
          const that = this
          this.beforeOpen(index, () => {
            that.open(index)
          })
        } else {
          this.open(index)
        }
      },
			
      getParentNode(name = undefined) {
        let parent = this.$parent;
        // 通过while历遍，这里主要是为了H5需要多层解析的问题
        while (parent) {
          // 父组件
          if (parent.$options && parent.$options.name !== name) {
            // 如果组件的name不相等，继续上一级寻找
            parent = parent.$parent;
          } else {
            return parent;
          }
        }
        return false;
      },
			
      addChild(node) {
        // console.log('add node: ', this)
        // const findRes = this.menuList.find(o => o.name === node.name)
        // if (findRes) {
        // 	findRes.instance = node
        // }
      },
			
      /**
       * 展开选项
       * @param {Number} openIndex
       */
      open(openIndex) {
        let showFlag = false
        const oldIndex = this.activeMenuIndex

        if (openIndex === this.activeMenuIndex) {
          this.activeMenuIndex = -1
        } else {
          this.activeMenuIndex = openIndex
          this.emitChangeEvt(openIndex)
        }
				
        this.$nextTick(() => {
          const children = this.getChildren()
          // this.children = children
					
          children.forEach((node, index) => {
            if (index === this.activeMenuIndex) {
              console.log('open node', node)
              node.opened = true
              showFlag = true
            } else if (index === oldIndex && this.activeMenuIndex === -1) {
              // 如果原来没有激活的索引则去执行关闭动画
              this.close(index)
            } else {
              // 直接关闭原来被激活的索引不执行动画
              node.opened = false
            }
          })
					
          if (showFlag) {
            this.$set(this.contentStyle, 'zIndex', 10)
            this.$set(this.maskStyle, 'opacity', 1)
            this.emitOpenEvt(this.activeMenuIndex)
          }
        })
      },
			
      getChildren() {
        let children = null
        // #ifdef MP-WEIXIN
        children = this.$children
        // #endif
        // #ifndef MP-WEIXIN
        children = this.$slots.default || []
        children = children.filter(o => Boolean(o.tag)).map(o => {
          return o.componentInstance
        })
        // #endif
        return children
      },
			
      /**
       * 执行关闭动画
       * @param {Number} index
       */
      close(index = -1) {
        this.$set(this.maskStyle, 'opacity', 0)
        let vm = null
        const children = this.getChildren()
        if (index !== -1) {
          vm = children[index]
        } else {
          vm = children.find(v => v.opened)
          this.activeMenuIndex = -1
        }
        if (!vm) {
          this.$set(this.contentStyle, 'zIndex', -1)
          return
        }
        // 动画执行完成后关闭延时关闭
        setTimeout(() => {
          vm.opend = false
          this.emitCloseEvt()
          this.$set(this.contentStyle, 'zIndex', -1)
        }, 300)
      },

      /**
       * 开启动画执行完毕后触发open事件
       * @param {Object} index
       */
      emitOpenEvt(index) {
        setTimeout(() => {
          this.$emit('open', index)
        }, 300)
      },
      /**
       * 切换下拉tab时触发
       * @param {Object} index
       */
      emitChangeEvt(index) {
        this.$emit('change', index)
      },
      /**
       * 关闭动画执行完成后触发close事件
       */
      emitCloseEvt() {
        this.$emit('close')
      },
			
      /**
       * 获取content内容高度
       */
      getContentHeight() {
        const that = this
        const windowHeight = uni.getSystemInfoSync().windowHeight
        uni.createSelectorQuery()
          .in(this)
          .select('.wk-dropdown')
          .boundingClientRect(res => {
            // console.log('getContentHeight: ', res)
            if (!res) return
            const height = windowHeight - res.bottom
            that.$set(that.contentStyle, 'height', height)
            that.maskStyle = {
              height: height + 'px',
              top: res.bottom + 'px',
              opacity: 0,
              zIndex: 1
            }
            this.contentHeight = height
          })
          .exec()
      }
    }
  }
</script>

<style scoped lang="scss">
	.wk-dropdown {
		position: relative;
		width: 100%;
		height: 80rpx;
		padding: 0 34rpx;
		@include center;
		
		.wk-dropdown-menu {
			width: 100%;
			display: flex;
			align-items: center;
			justify-content: space-between;
			
			&_item {
				flex: 1;
				font-size: 26rpx;
				@include center;
				
				&__text {
					line-height: 1;
					margin: 0 10rpx;
				}
				
				&__left-icon {
					font-size: 26rpx;
					align-content: center;
				}
				
				&__icon {
					transform: rotate(90deg);
					font-size: 24rpx;
					align-content: center;
					will-change: transform;
					transition: transform ease .3s;
				}
			}
			
			.wk-dropdown-menu_item.active {
				.wk-dropdown-menu_item__icon {
					transform: rotate(-90deg);
				}
			}
		}
		
		.wk-dropdown-content {
			position: absolute;
			top: 80rpx;
			left: 0;
			z-index: 11;
			width: 750rpx;
			font-size: 28rpx;
			overflow: hidden;

			&__pop {
				position: absolute;
				z-index: 100;
				width: 100%;
				background-color: white;
				border-top: 1rpx solid $border-color;
				will-change: transform;
				transition: transform ease 0.3s;
				transform: translateY(-100%);
				overflow: hidden;
				display: flex;
				flex-direction: column;
			}
			&__mask {
				position: fixed;
				bottom: 0;
				left: 0;
				width: 100%;
				background-color: rgba(0, 0, 0, .4);
				opacity: 0;
				will-change: opacity;
				transition: opacity ease 0.3s;
			}
		}
	}
</style>
