<template>
  <transition
    name="bx-animate-slide"
    v-on="transitionListeners"
    >
    <div
      ref="layer"
      class="bx-sheets-layer"
      v-if="value"
      >
      <div
        ref="header"
        class="bx-sheets-header"
        v-if="!hideHeader"
        >
        <slot name="header">
          <div class="bx-sheets-header-inner">
            <div class="bx-sheets-title">
              {{ title }}
            </div>
            <div
              class="bx-sheets-close"
              @click="closePopup"
              >
              <bxs-icon name="close" />
            </div>
          </div>
        </slot>
      </div>
      <div
        ref="content"
        class="bx-sheets-content"
        :class="!useBScroll && 'bx-sheets-content--scroll'"
        >
        <div
          ref="scroll"
          class="bx-sheets-scroll"
          >
          <slot />
        </div>
      </div>
      <div
        ref="footer"
        class="bx-sheets-footer"
        v-if="!hideFooter"
        >
        <slot name="footer" />
      </div>
    </div>
  </transition>
</template>
<script>
import BScroll from 'better-scroll'
import Popup from '../mixins/popup/index'
import Icon from '../icon/index'
import { create } from '../utils/index'

const [MAX_HEIGHT_RATE, MIN_HEIGHT_RATE] = [0.7, 0.4]
export default create({
  name: 'bottom-sheets',
  mixins: [Popup],
  props: {
    // 半屏浮层的固定高度
    height: {
      type: Number,
      default: null,
    },
    // 是否使用better-scroll
    useBScroll: {
      type: Boolean,
      default: false,
    },
    // 是否隐藏浮层顶部栏
    hideHeader: {
      type: Boolean,
      default: false,
    },
    // 是否隐藏浮层底部栏
    hideFooter: {
      type: Boolean,
      default: false,
    },
    // 顶部栏标题
    title: {
      type: String,
      default: '',
    },
  },
  computed: {
    transitionListeners() {
      const existEvents = {
        appear: this.enter,
        enter: this.enter,
        'after-enter': this.afterEnter,
      }
      return Object.assign(
        {},
        this.listenersEmit(
          [
            'appear',
            'before-enter',
            'enter',
            'after-enter',
            'enter-cancelled',
            'leave',
            'after-leave',
            'leave-cancelled',
          ],
          existEvents,
        ),
      )
    },
  },
  methods: {
    // 关闭浮层
    closePopup() {
      this.$emit('input', false)
    },
    // 设置正文内容的位置
    setContentPosition() {
      const $header = this.$refs.header
      const $footer = this.$refs.footer
      this.headerHeight = 0
      if ($header) {
        this.headerHeight = $header.clientHeight
        this.wrapper.style.top = `${$header.clientHeight}px`
      }
      if ($footer) {
        this.wrapper.style.bottom = `${$footer.clientHeight}px`
      }
    },
    setHeight(el, height) {
      const $el = el
      $el.style.height = `${height}px`
    },
    // 设置浮层的高度最大70%，最小40%
    setLayerHeight() {
      const $scroll = this.wrapper.children[0]
      const layerHeight = parseInt($scroll.clientHeight + this.headerHeight, 10)
      const maxHeight = parseInt(
        window.screen.availHeight * MAX_HEIGHT_RATE,
        10,
      )
      const minHeight = parseInt(
        window.screen.availHeight * MIN_HEIGHT_RATE,
        10,
      )
      if (this.height) {
        let displayHeight = this.height
        if (displayHeight >= maxHeight) {
          displayHeight = maxHeight
        }
        if (displayHeight <= minHeight) {
          displayHeight = minHeight
        }
        this.setHeight(this.layer, displayHeight)
      } else if (layerHeight >= maxHeight) {
        this.setHeight(this.layer, maxHeight)
      } else if (layerHeight <= minHeight) {
        this.setHeight(this.layer, minHeight)
      } else {
        this.setHeight(this.layer, layerHeight)
      }
    },
    initPopup() {
      this.layer = this.$refs.layer
      this.wrapper = this.$refs.content
      if (this.layer) {
        this.setContentPosition()
        this.setLayerHeight()
        this.$emit('domReady', this.$refs)
      }
    },
    // 动画enter回调
    enter() {
      this.initPopup()
    },
    // 动画after-enter回调
    afterEnter() {
      // TODO: （#83）无视滚动区域是否超出父容器，一律初始化 BSCroll，用以支持浮层打开情况下内容动态变动的情形
      // 仅确定提供 BSCroll 实例，使用者仍需在内容变动后自行调用 scroll.refresh()
      // 因 BSCroll 只关心默认 slot 的内容，header 和 footer slot 中的内容变动暂无法支持
      // 后期可能需要更周到处理
      if (this.useBScroll) {
        // eslint-disable-next-line
        var scroll = new BScroll(this.wrapper)
        this.$emit('bscroll', scroll)
      }
    },
    // 给事件添加 $emit
    listenersEmit(eventNames, existEvents) {
      const listeners = {}
      eventNames.forEach(name => {
        const eventFunc = existEvents[name]
        listeners[name] = el => {
          if (eventFunc) {
            eventFunc.call(this, el)
          }
          this.$emit(name, el)
        }
      })
      return listeners
    },
  },
  components: {
    [Icon.name]: Icon,
  },
})
</script>
<style lang="postcss">
@import './index.css';
@import '../../src/style/animate.css';
</style>
