content: import React from 'react';
  import domUtils from './utils/domUtils';
  import EventListener from './utils/EventListener';
  
  const AffixMixin = {
    propTypes: {
      offset: React.PropTypes.number,
      offsetTop: React.PropTypes.number,
      offsetBottom: React.PropTypes.number
    },
  
    getInitialState() {
      return {
        affixClass: 'affix-top'
      };
    },
  
    getPinnedOffset(DOMNode) {
      if (this.pinnedOffset) {
        return this.pinnedOffset;
      }
  
      DOMNode.className = DOMNode.className.replace(/affix-top|affix-bottom|affix/, '');
      DOMNode.className += DOMNode.className.length ? ' affix' : 'affix';
  
      this.pinnedOffset = domUtils.getOffset(DOMNode).top - window.pageYOffset;
  
      return this.pinnedOffset;
    },
  
    checkPosition() {
      let DOMNode, scrollHeight, scrollTop, position, offsetTop, offsetBottom,
          affix, affixType, affixPositionTop;
  
      // TODO: or not visible
      if (!this.isMounted()) {
        return;
      }
  
      DOMNode = React.findDOMNode(this);
      scrollHeight = document.documentElement.offsetHeight;
      scrollTop = window.pageYOffset;
      position = domUtils.getOffset(DOMNode);
  
      if (this.affixed === 'top') {
        position.top += scrollTop;
      }
  
      offsetTop = this.props.offsetTop != null ?
        this.props.offsetTop : this.props.offset;
      offsetBottom = this.props.offsetBottom != null ?
        this.props.offsetBottom : this.props.offset;
  
      if (offsetTop == null && offsetBottom == null) {
        return;
      }
      if (offsetTop == null) {
        offsetTop = 0;
      }
      if (offsetBottom == null) {
        offsetBottom = 0;
      }
  
      if (this.unpin != null && (scrollTop + this.unpin <= position.top)) {
        affix = false;
      } else if (offsetBottom != null && (position.top + DOMNode.offsetHeight >= scrollHeight - offsetBottom)) {
        affix = 'bottom';
      } else if (offsetTop != null && (scrollTop <= offsetTop)) {
        affix = 'top';
      } else {
        affix = false;
      }
  
      if (this.affixed === affix) {
        return;
      }
  
      if (this.unpin != null) {
        DOMNode.style.top = '';
      }
  
      affixType = 'affix' + (affix ? '-' + affix : '');
  
      this.affixed = affix;
      this.unpin = affix === 'bottom' ?
        this.getPinnedOffset(DOMNode) : null;
  
      if (affix === 'bottom') {
        DOMNode.className = DOMNode.className.replace(/affix-top|affix-bottom|affix/, 'affix-bottom');
        affixPositionTop = scrollHeight - offsetBottom - DOMNode.offsetHeight - domUtils.getOffset(DOMNode).top;
      }
  
      this.setState({
        affixClass: affixType,
        affixPositionTop
      });
    },
  
    checkPositionWithEventLoop() {
      setTimeout(this.checkPosition, 0);
    },
  
    componentDidMount() {
      this._onWindowScrollListener =
        EventListener.listen(window, 'scroll', this.checkPosition);
      this._onDocumentClickListener =
        EventListener.listen(domUtils.ownerDocument(this), 'click', this.checkPositionWithEventLoop);
    },
  
    componentWillUnmount() {
      if (this._onWindowScrollListener) {
        this._onWindowScrollListener.remove();
      }
  
      if (this._onDocumentClickListener) {
        this._onDocumentClickListener.remove();
      }
    },
  
    componentDidUpdate(prevProps, prevState) {
      if (prevState.affixClass === this.state.affixClass) {
        this.checkPositionWithEventLoop();
      }
    }
  };
  
  export default AffixMixin;
  