<!--
* @description
* @fileName dof-popover
* @author liangzw
* @date 2021/01/26 11:35:06
!-->
<template>
  <div class="wrapper">
    <div class="g-cover" ref="dof-cover" v-if="show" @click="clickCover" :style="coverStyle"></div>
    <div ref="dof-popover" class="g-popover" v-if="show && buttons.length" :style="contentStyle">
      <div :class="['u-popover-arrow', theme !== 'white' && 'u-popover-theme-dark']" :style="arrowStyle"></div>
      <scroller
        show-scrollbar="false"
        :class="['u-popover-inner', theme !== 'white' && 'u-popover-theme-dark']"
        :style="popoverInnerStyle"
        ref="dof-inner-popover"
      >
        <div
          :class="[
            'i-btn',
            i === buttons.length - 1 ? 'i-btn-noborder' : '',
            layoutDirection == 'row' ? 'row-layout' : 'column-layout',
            layoutDirection == 'row' && i != buttons.length - 1 ? 'borderRight' : '',
            layoutDirection == 'column' && i != buttons.length - 1 ? 'borderBottom' : ''
          ]"
          v-for="(item, i) in buttons"
          :key="i"
          @click="dofButtonClicked(i, item.key)"
        >
          <image :src="item.icon" v-if="item.icon && !_isColmo" class="btn-icon"></image>
          <dof-iconfont
            v-if="item.icon && _isColmo"
            :code="item.icon"
            :size="56"
            :color="textStyle.color ? textStyle.color : 'rgba(255,255,255,0.80)'"
            @dofIconFontClicked="dofButtonClicked(i, item.key)"
          ></dof-iconfont>
          <text :class="['btn-text', theme !== 'white' && 'btn-text-theme-dark']" :style="textStyle">{{
            item.text
          }}</text>
        </div>
      </scroller>
    </div>
    <div ref="dof-popover" class="g-popover" v-if="show && !buttons.length" :style="contentStyle" @click="() => {}">
      <div :class="['u-popover-arrow', theme !== 'white' && 'u-popover-theme-dark']" :style="arrowStyle"></div>
      <div class="content-inner" ref="dof-inner-popover" :style="innerContentStyle">
        <slot>
          <text class="textContent" :style="textStyle">{{ textContent }}</text>
          <slot name="icon">
            <div class="closeBox" v-if="isShowClose" @click="$emit('clickedCloseBtn')">
              <image v-if="!_isColmo" :src="_isDiablo ? imgs.closeDiablo : imgs.close" class="closeIcon"></image>
              <dof-iconfont
                v-else
                :code="'\u4725'"
                :size="32"
                :color="_isColmo ? 'rgba(255,255,255,0.80)' : '#1E2E37'"
                @dofIconFontClicked="$emit('clickedCloseBtn')"
              ></dof-iconfont>
            </div>
          </slot>
        </slot>
      </div>
    </div>
  </div>
</template>

<script>
const { env } = weex.config
const animation = weex.requireModule('animation')
const dom = weex.requireModule('dom')
import imgs from './imgs'
import ColmoMixin from '../../mixins/colmo'
import DiabloMixin from '../../mixins/diablo'
import DofIconfont from '../dof-iconfont'
export default {
  mixins: [ColmoMixin, DiabloMixin],
  components: { DofIconfont },
  props: {
    mode: {
      type: String,
      default: 'common'
    },
    theme: {
      type: String,
      default: 'white'
    },
    layoutDirection: {
      type: String,
      default: 'column'
    },
    buttons: {
      type: Array,
      default: () => []
    },
    position: {
      type: Object,
      default: () => ({
        x: 0,
        y: 0
      })
    },
    arrowPosition: {
      type: Object,
      default: () => ({
        pos: 'top',
        x: 0,
        y: 0
      })
    },
    coverColor: {
      type: String,
      default: 'rgba(0, 0, 0, 0.1)'
    },
    hasAnimation: {
      type: Boolean,
      default: true
    },
    textStyle: {
      type: Object,
      default: () => ({})
    },
    textContent: {
      type: String,
      default: ''
    },
    innerBgColor: {
      type: String,
      default: ''
    },
    isClickCoverHide: {
      type: Boolean,
      default: true
    },
    isShowClose: {
      type: Boolean,
      default: false
    },
    width: {
      type: Number,
      default: 0
    },
    elPos: {
      type: Object,
      default: null
    }
  },
  data: () => ({
    sHeight: (env.deviceHeight / env.deviceWidth) * 750,
    show: false,
    showIn: false,
    imgs,
    position_: { x: 0, y: 0 }
  }),
  watch: {
    elPos(val) {
      setTimeout(() => {
        this.handleElPos(val)
      }, 100)
    },
    position: {
      handler(val) {
        if (!this.elPos) {
          this.position_ = val
        }
      },
      immediate: true
    }
  },
  created() {},
  computed: {
    coverStyle() {
      return this.coverColor
        ? { backgroundColor: this.coverColor, opacity: this.hasAnimation || !this.showIn ? '0' : '1' }
        : ''
    },
    transformOrigin() {
      const { x = 0, y = 0, pos = 'top' } = this.arrowPosition
      let _origins = []
      switch (pos) {
        case 'top':
        case 'bottom':
          _origins = [x < 0 ? 'right' : 'left', pos]
          break
        case 'left':
        case 'right':
          _origins = [pos, y < 0 ? 'bottom' : 'top']
          break
      }
      return _origins.join(' ')
    },
    contentTransform() {
      const { pos = 'top' } = this.arrowPosition
      let { x = 0, y = 0 } = this.arrowPosition
      const _translates = ['scale(0)']
      if (x >= 0 && x < 22) {
        x = 22
      } else if (x < 0 && x > -22) {
        x = -22
      }
      if (y >= 0 && y < 22) {
        y = 22
      } else if (y < 0 && y > -22) {
        y = -22
      }
      switch (pos) {
        case 'top':
        case 'bottom':
          _translates[1] = `translateX(${x < 0 ? x - 15 : x + 15}px)`
          break
        case 'left':
        case 'right':
          _translates[1] = `translateY(${y < 0 ? y - 15 : y + 15}px)`
          break
      }
      return _translates.join(' ')
    },
    contentStyle() {
      const { x = 0, y = 0 } = this.position_
      const style = {}
      if (!this.elPos) {
        x < 0 ? (style.right = `${-x}px`) : (style.left = `${x}px`)
        y < 0 ? (style.bottom = `${-y}px`) : (style.top = `${y}px`)
      } else {
        if (this.arrowPosition.pos === 'bottom') {
          style.left = `${x}px`
          style.top = `${y}px`
        } else {
          style.left = `${x}px`
          style.top = `${y}px`
        }
      }

      style.opacity = this.hasAnimation || !this.showIn ? '0' : '1'
      style.transform = this.hasAnimation || !this.showIn ? this.contentTransform : 'scale(1)'
      style.transformOrigin = this.transformOrigin
      return style
    },
    arrowStyle() {
      let { x = 0, y = 0 } = this.arrowPosition
      const { pos = 'top' } = this.arrowPosition
      const style = {
        backgroundColor: this.bgColor
      }
      switch (pos) {
        case 'top':
          style.top = '6px'
        case 'bottom': //eslint-disable-line
          !style.top && (style.bottom = '6px')
          // style.transform = 'rotateZ(45deg) rotateY(45deg)'
          if (x >= 0 && x < 22) {
            x = 22
          } else if (x < 0 && x > -22) {
            x = -22
          }
          x < 0 ? (style.right = `${-x}px`) : (style.left = `${x}px`)
          break
        case 'left':
          style.left = '6px'
        case 'right': //eslint-disable-line
          !style.left && (style.right = '6px')
          // style.transform = 'scaleY(0.8) rotate(45deg)'
          if (y >= 0 && y < 22) {
            y = 22
          } else if (y < 0 && y > -22) {
            y = -22
          }
          y < 0 ? (style.bottom = `${-y}px`) : (style.top = `${y}px`)
          break
        default:
          break
      }
      return style
    },
    popoverInnerStyle() {
      let { layoutDirection } = this
      if (layoutDirection === 'row') {
        return {
          ...this.innerContentStyle,
          flexDirection: 'row'
        }
      } else {
        return {
          ...this.innerContentStyle,
          flexDirection: 'column'
        }
      }
    },
    btnInnerStyle() {
      let { layoutDirection } = this
      if (layoutDirection === 'row') {
        return {
          borderRightWidth: '1px'
        }
      } else {
        return {
          borderBottomWidth: '1px'
        }
      }
    },
    bgColor() {
      if (this._isColmo && this.buttons.length) return '#313338'
      return this.innerBgColor ? this.innerBgColor : this.theme === 'dark' ? '#000' : this._isColmo ? '#43464d' : '#fff'
    },
    innerContentStyle() {
      const style = {
        backgroundColor: this.bgColor
      }
      if (this.width) style.width = this.width + 'px'
      if (this._isColmo && this.isShowClose) style.paddingRight = '10px'
      return style
    }
  },
  methods: {
    dofPopoverShow() {
      if (this.animationLock) {
        return
      }
      if (this.elPos.el) this.handleElPos(this.elPos)
      this.show = true
      if (this.hasAnimation) {
        setTimeout(() => this.dofPopoverAnimationShow(), 40)
      } else {
        setTimeout(() => (this.showIn = true), 40)
      }
    },
    /**
     * smooth in
     **/
    dofPopoverAnimationShow() {
      const popoverEl = this.$refs['dof-popover']
      const coverEl = this.$refs['dof-cover']
      if (!coverEl || !popoverEl) {
        return
      }
      this.setAnimationLock()
      let a1End = false
      let a2End = false
      animation.transition(
        popoverEl,
        {
          styles: {
            opacity: 1,
            transform: 'scale(1)',
            transformOrigin: this.transformOrigin
          },
          delay: 0,
          duration: 250,
          timingFunction: 'ease-out'
        },
        e => {
          a1End = true
          if (a1End && a2End) {
            this.animationLock = false
          }
        }
      )

      animation.transition(
        coverEl,
        {
          styles: {
            opacity: 1
          },
          delay: 0,
          duration: 250,
          timingFunction: 'ease-in'
        },
        e => {
          a2End = true
          if (a1End && a2End) {
            this.animationLock = false
          }
        }
      )
    },
    dofButtonClicked(index, key) {
      if (this.animationLock) {
        return
      }
      this.$emit('dofPopoverButtonClicked', { key, index })
      this.hideAction()
    },
    /**
     * 隐藏操作
     */
    hideAction() {
      if (this.animationLock) {
        return
      }
      if (this.hasAnimation && this.show) {
        this.setAnimationLock()
        const popoverEl = this.$refs['dof-popover']
        const coverEl = this.$refs['dof-cover']
        if (!popoverEl || !coverEl) {
          return
        }
        let a1End = false
        let a2End = false
        animation.transition(
          popoverEl,
          {
            styles: {
              opacity: 0,
              transform: this.contentTransform,
              transformOrigin: this.transformOrigin
            },
            duration: 250
          },
          () => {
            a1End = true
            if (a1End && a2End) {
              this.show = false
              this.showIn = false
              this.animationLock = false
            }
          }
        )
        animation.transition(
          coverEl,
          {
            styles: {
              opacity: 0
            },
            duration: 250
          },
          () => {
            a2End = true
            if (a1End && a2End) {
              this.show = false
              this.showIn = false
              this.animationLock = false
            }
          }
        )
      } else {
        this.show = false
        this.showIn = false
      }
    },
    /**
     * 设置动画锁
     */
    setAnimationLock() {
      this.animationLock = true
    },
    clickCover() {
      this.isClickCoverHide && this.hideAction()
      this.$emit('dofPopoverCoverClicked')
    },
    getPosition(el) {
      return new Promise((resolve, reject) => {
        dom.getComponentRect(el, result => {
          let size = result.size || {}
          resolve(size)
        })
      })
    },
    async handleElPos(val) {
      if (!val.el) return
      const res = await this.getPosition(val.el)
      if (this.arrowPosition.pos === 'top' || !this.arrowPosition.pos) {
        this.position_ = { x: res.left - 15 + this.elPos.offsetX, y: res.top + res.height + this.elPos.offsetY }
      }
      if (this.arrowPosition.pos === 'bottom') {
        this.position_ = { x: res.left - 15 + this.elPos.offsetX, y: res.top - 110 - 15 + this.elPos.offsetY }
      }
      if (this.arrowPosition.pos === 'left') {
        this.position_ = { x: res.left + res.width + 10 + this.elPos.offsetX, y: res.top - 15 + this.elPos.offsetY }
      }
      if (this.arrowPosition.pos === 'right') {
        this.position_ = { x: res.left - 285 + this.elPos.offsetX, y: res.top - 15 + this.elPos.offsetY }
      }
    }
  }
}
</script>

<style scoped>
.wrapper {
  z-index: 999;
}
.g-cover {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  /* background-color: rgba(0, 0, 0, 0.4); */
  z-index: 1;
}
.g-popover {
  position: fixed;
  padding: 15px;
  z-index: 10;
}
.u-popover-arrow {
  position: absolute;
  /* border-radius: 4px; */
  width: 36px;
  height: 36px;
  background-color: #ffffff;
  transform: rotateZ(45deg);
}
.u-popover-inner {
  border-radius: 16px;
  background-color: #ffffff;
  max-width: 686px;
}
.content-inner {
  border-radius: 16px;
  max-width: 686px;
  padding: 24px;
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
}
.closeBox {
  padding-top: 10px;
  padding-bottom: 10px;
  padding-right: 0px;
  padding-left: 10px;
}
.closeIcon {
  width: 18px;
  height: 18px;
}

.u-popover-theme-white {
  background-color: #ffffff;
}
.u-popover-theme-dark {
  background-color: #1E2E37;
}
.i-btn {
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  /* margin-left: 10px;
  margin-right: 10px; */
  /* padding-left: 20px; */
  /* padding-right: 20px; */
}
.row-layout {
  padding-left: 36px;
  padding-right: 36px;
}
.column-layout {
  padding-top: 2px;
  padding-bottom: 2px;
}
.borderRight {
  border-right-width: 1px;
  border-right-color: #eaeaeb;
}
.borderBottom {
  border-bottom-width: 1px;
  border-bottom-color: #eaeaeb;
}
.i-btn-noborder {
  border-bottom-color: #ffffff;
}
.btn-icon {
  width: 32px;
  height: 32px;
  margin-right: 16px;
}
.btn-text {
  flex: 1;
  height: 96px;
  font-size: 28px;
  line-height: 96px;
  color: #232323;
  margin-left: 8px;
}
.btn-text-theme-dark {
  color: #ffffff;
}
.text-align-center {
  text-align: center;
}
.textContent {
  flex: 1;
  font-family: PingFangSC-Regular;
  font-size: 24px;
  color: #616C73;
  font-weight: 400;
}
</style>

<style scoped src="./colmo.css"></style>
<style scoped src="./diablo.css"></style>
