text: import { context } from './context';
  import { TouchMixin } from '../touch';
  import { PortalMixin } from '../portal';
  import { CloseOnPopstateMixin } from '../close-on-popstate';
  import { on, off, preventDefault } from '../../utils/dom/event';
  import { openOverlay, closeOverlay, updateOverlay } from './overlay';
  import { getScrollEventTarget } from '../../utils/dom/scroll';
  
  export const PopupMixin = {
    mixins: [
      TouchMixin,
      CloseOnPopstateMixin,
      PortalMixin({
        afterPortal() {
          if (this.overlay) {
            updateOverlay();
          }
        }
      })
    ],
  
    props: {
      // whether to show popup
      value: Boolean,
      // whether to show overlay
      overlay: Boolean,
      // overlay custom style
      overlayStyle: Object,
      // overlay custom class name
      overlayClass: String,
      // whether to close popup when click overlay
      closeOnClickOverlay: Boolean,
      // z-index
      zIndex: [Number, String],
      // prevent body scroll
      lockScroll: {
        type: Boolean,
        default: true
      },
      // whether to lazy render
      lazyRender: {
        type: Boolean,
        default: true
      }
    },
  
    data() {
      return {
        inited: this.value
      };
    },
  
    computed: {
      shouldRender() {
        return this.inited || !this.lazyRender;
      }
    },
  
    watch: {
      value(val) {
        const type = val ? 'open' : 'close';
        this.inited = this.inited || this.value;
        this[type]();
        this.$emit(type);
      },
  
      overlay: 'renderOverlay'
    },
  
    mounted() {
      if (this.value) {
        this.open();
      }
    },
  
    /* istanbul ignore next */
    activated() {
      if (this.value) {
        this.open();
      }
    },
  
    beforeDestroy() {
      this.close();
  
      if (this.getContainer && this.$parent && this.$parent.$el) {
        this.$parent.$el.appendChild(this.$el);
      }
    },
  
    /* istanbul ignore next */
    deactivated() {
      this.close();
    },
  
    methods: {
      open() {
        /* istanbul ignore next */
        if (this.$isServer || this.opened) {
          return;
        }
  
        // cover default zIndex
        if (this.zIndex !== undefined) {
          context.zIndex = this.zIndex;
        }
  
        this.opened = true;
        this.renderOverlay();
  
        if (this.lockScroll) {
          on(document, 'touchstart', this.touchStart);
          on(document, 'touchmove', this.onTouchMove);
  
          if (!context.lockCount) {
            document.body.classList.add('van-overflow-hidden');
          }
          context.lockCount++;
        }
      },
  
      close() {
        if (!this.opened) {
          return;
        }
  
        if (this.lockScroll) {
          context.lockCount--;
          off(document, 'touchstart', this.touchStart);
          off(document, 'touchmove', this.onTouchMove);
  
          if (!context.lockCount) {
            document.body.classList.remove('van-overflow-hidden');
          }
        }
  
        this.opened = false;
        closeOverlay(this);
        this.$emit('input', false);
      },
  
      onTouchMove(event) {
        this.touchMove(event);
        const direction = this.deltaY > 0 ? '10' : '01';
        const el = getScrollEventTarget(event.target, this.$el);
        const { scrollHeight, offsetHeight, scrollTop } = el;
        let status = '11';
  
        /* istanbul ignore next */
        if (scrollTop === 0) {
          status = offsetHeight >= scrollHeight ? '00' : '01';
        } else if (scrollTop + offsetHeight >= scrollHeight) {
          status = '10';
        }
  
        /* istanbul ignore next */
        if (
          status !== '11' &&
          this.direction === 'vertical' &&
          !(parseInt(status, 2) & parseInt(direction, 2))
        ) {
          preventDefault(event, true);
        }
      },
  
      renderOverlay() {
        if (this.$isServer || !this.value) {
          return;
        }
  
        this.$nextTick(() => {
          this.updateZIndex(this.overlay ? 1 : 0);
  
          if (this.overlay) {
            openOverlay(this, {
              zIndex: context.zIndex++,
              duration: this.duration,
              className: this.overlayClass,
              customStyle: this.overlayStyle
            });
          } else {
            closeOverlay(this);
          }
        });
      },
  
      updateZIndex(value = 0) {
        this.$el.style.zIndex = ++context.zIndex + value;
      }
    }
  };
  