<template>
  <div ref="placeholderNode" :style="{ ...placeholderNodeStyle }">
    <div ref="fixedNode" :style="{ ...fixedNodeStyle }">
      <slot />
    </div>
  </div>
</template>

<script>
import { TRIGGER_EVENTS, getDefaultTarget } from './utils'
import addDOMEventListener from 'add-dom-event-listener'

import _ from 'lodash'

export default {
  name: 'Affix',
  props: {
    /**
     * 距离窗口顶部达到指定偏移量后触发
     */
    offsetTop: {
      type: Number,
      required: false,
      default: () => null
    },
    offset: {
      type: Number,
      required: false,
      default: () => null
    },
    /** 距离窗口底部达到指定偏移量后触发 */
    offsetBottom: {
      type: Number,
      required: false,
      default: () => null
    },
    /** 固定状态改变时触发的回调函数 */
    // onChange?: (_Affixed?: boolean) => void;
    /** 设置 _Affix 需要监听其滚动事件的元素，值为一个返回对应 DOM 元素的函数 */
    target: {
      type: Function,
      required: false,
      default: () => getDefaultTarget()
    },
    prefixCls: {
      type: String,
      required: false,
      default: () => null
    }
  },
  data() {
    this.lazyUpdatePosition = _.throttle(this.lazyUpdatePosition, 300)
    return {
      placeholderNodeStyle: '',
      fixedNodeStyle: '',
      entity: {
        target: null,
        affixList: [],
        eventHandlers: {}
      }
    }
  },
  mounted() {
    // console.log(this.target().Target)
    this.init()
  },
  // 销毁事件
  destroyed() {
    this.unInit()
  },
  methods: {
    init() {
      const { entity } = this
      const targetNode = this.target()
      TRIGGER_EVENTS.forEach((eventName) => {
        // targetNode.addEventListener(eventName, () => {
        //   this.lazyUpdatePosition()
        // })
        entity.eventHandlers[eventName] = addDOMEventListener(
          targetNode,
          eventName,
          () => {
            this.lazyUpdatePosition()
          }
        )
      })
      this.lazyUpdatePosition()
    },
    // @ts-ignore TS6133
    prepareMeasure() {
      this.fixedNodeStyle = null
      this.placeholderNodeStyle = null
      this.$forceUpdate()
    },
    getOffsetTop() {
      const { offset, offsetBottom } = this
      let { offsetTop } = this
      if (typeof offsetTop === 'undefined') {
        offsetTop = offset
      }

      if (offsetBottom === undefined && offsetTop === undefined) {
        offsetTop = 0
      }
      return offsetTop
    },
    lazyUpdatePosition() {
      const targetNode = this.target()
      const offsetTop = this.getOffsetTop()
      // console.log(102, this.$refs, targetNode.scrollTop)
      if (targetNode.scrollTop < offsetTop) {
        this.prepareMeasure()
        return
      }

      const placeholderReact = this.$refs.placeholderNode
      this.fixedNodeStyle = {
        position: 'fixed',
        top: `${offsetTop}px`,
        zIndex: 999,
        width: placeholderReact.offsetWidth + 'px',
        height: placeholderReact.offsetHeight + 'px'
      }
      this.placeholderNodeStyle = {
        width: placeholderReact.offsetWidth + 'px',
        height: placeholderReact.offsetHeight + 'px'
      }
    },
    unInit() {
      const { entity } = this
      // const targetNode = this.target()
      // console.log(123, targetNode)
      TRIGGER_EVENTS.forEach((eventName) => {
        // targetNode.removeEventListener(eventName, () => {
        //   this.lazyUpdatePosition()
        // })
        // entity.eventHandlers[eventName]
        const handler = entity.eventHandlers[eventName]
        if (handler && handler.remove) {
          handler.remove()
        }
      })
    }
  }
}
</script>

<style scoped lang="less"></style>
