<template>
  <div style="overflow: auto;" :style="affixStyle">
    <slot></slot>
  </div>
</template>

<script>
const computedStyle = (el, prop) => {
  var style = window.getComputedStyle ? window.getComputedStyle(el) : el.currentStyle
  if (style) {
    return style[prop.replace(/-(\w)/gi, function (word, letter) { return letter.toUpperCase() })]
  }
}

export default {
  props: {
    height: {
      type: String
    },
    width: {
      type: String
    },
    offsetTop: {
      type: Number,
      default: 10
    },
    offsetBottom: {
      type: Number,
      default: 70
    },
    onChange: {
      type: Function
    },
    holder: {
      type: Boolean,
      default: false
    }
  },
  watch: {
    width(val){
      this.defaultStyle.width = val
    }
  },
  data(){
    let defaultStyle = {}
    if (this.height){
      defaultStyle.height = this.height
    }
    if (this.width){
      defaultStyle.width = this.width
    }
    return {
      offset: null,
      fixed: false,
      defaultStyle: defaultStyle,
      affixStyle: defaultStyle
    }
  },
  mounted () {
    $(window).on('scroll', this.updatePosition)
    $(window).on('resize', this.handleWindowResize)
    this.setOrigin()
    this.setContainerOffset()
  },
  beforeDestroy(){
    $(window).off('scroll', this.updatePosition)
    $(window).off('resize', this.handleWindowResize)
  },
  methods: {
    setContainerOffset(){
      this.offset = Object.assign($(this.$el).offset(), {
        width: this.$el.offsetWidth,
        height: this.$el.offsetHeight
      })
    },
    updatePosition(){
      const offset = this.offset
      const offsetTop = this.offsetTop
      const offsetBottom = this.offsetBottom
      const overflow = window.scrollY - (offset.top - offsetTop) >= 0

      // let fixed = overflow ? true : false;
      let fixed = !!overflow
      let affixStyle = overflow ? {
        position: 'fixed',
        top: offsetTop + 'px',
        bottom: offsetBottom + 'px',
        left: offset.left + 'px',
        boxShadow: 'rgba(99, 99, 99, 0.2) 2px 2px 6px',
        zIndex: 1,
        width: this.defaultStyle.width && this.defaultStyle.width !== 'auto' ? this.defaultStyle : offset.width + 'px',
        height: 'auto'
      } : this.defaultStyle

      if (fixed !== this.fixed) {
        this.fixed = fixed
        if (fixed){
          this.setHolder()
        } else {
          if (this.$el.style.height !== 'auto'){
            console.warn('请不要通过style属性设置affix-viewport组件的高度，请使用height属性')
          }

          Object.assign(this.$el.style, this.origin)
          this.removeHolder()
        }
        this.affixStyle = affixStyle
        this.onChange && this.onChange(fixed)
      }
    },
    handleWindowResize(){
      setTimeout(_ => {
        this.setContainerOffset()
      }, 1)
    },
    setOrigin () {
      if (!this.origin){
        this.origin = {}
      }
      var computedStyles = ['top', 'left', 'bottom', 'position']
      var origin = this.origin
      var el = this.$el
      computedStyles.forEach(function (prop) {
        origin[prop] = computedStyle(el, prop)
      })
    },
    setHolder() {
      if (!this.holder || this.holderEl) return
      var el = this.holderEl = document.createElement('div')
      el.style.height = this.$el.clientHeight + 'px'
      el.style.width = this.$el.clientWidth + 'px'
      this.$el.parentNode.insertBefore(el, this.$el)
    },
    removeHolder () {
      if (this.holderEl && this.holderEl.parentNode){
        this.holderEl.parentNode.removeChild(this.holderEl)
      }
      this.holderEl = null
    }
  }
}
</script>
