import { mergeProps as _mergeProps, isVNode as _isVNode, withDirectives as _withDirectives, vShow as _vShow, createVNode as _createVNode } from "vue";
import { cloneVNode, computed, defineComponent, getCurrentInstance, onMounted, ref, Teleport, Transition, watchEffect } from 'vue';
import { getComponent, getSlot } from '../_util/props-util';

function _isSlot(s) {
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !_isVNode(s);
}

const preCls = 'x-drawer';
const Drawer = defineComponent({
  name: preCls,
  props: {
    title: String,
    visible: Boolean,
    width: {
      type: [Number, String],
      default: 396
    },
    mask: {
      type: Boolean,
      default: true
    },
    maskClosable: {
      type: Boolean,
      default: true
    },
    to: {
      type: [String, HTMLElement, Function],
      default: 'body'
    }
  },
  inheritAttrs: false,
  emits: ['update:visible'],

  setup(props, {
    attrs,
    emit
  }) {
    const {
      proxy: vm
    } = getCurrentInstance();

    function onClose() {
      setVisible(false);
    }

    function onMaskClick() {
      if (!props.maskClosable) return;
      onClose();
    }

    function setVisible(visible) {
      emit('update:visible', visible);
    }

    const isMounted = ref(false);
    onMounted(() => {
      isMounted.value = true;
    }); // 禁用 parent 滚动

    let parentOverflow; // undefined 是必要的

    watchEffect(() => {
      const {
        visible,
        to
      } = props;
      const parentEle = typeof to === 'string' ? document.querySelector(to) : typeof to === 'function' ? to() : to;
      if (!parentEle) return;

      if (visible) {
        parentOverflow = parentEle.style.overflow;
        parentEle.style.overflow = 'hidden';
      } else if (parentOverflow !== 'hidden') {
        parentEle.style.overflow = parentOverflow;
      }
    });
    const headerRef = computed(() => {
      var _getComponent;

      let title = getComponent(vm, 'title');
      let header = (_getComponent = getComponent(vm, 'header')) === null || _getComponent === void 0 ? void 0 : _getComponent[0];
      if (!header && !title) return undefined;
      const extraProps = {
        class: `${preCls}_header`
      };

      if (header) {
        header = cloneVNode(header, extraProps);
      } else {
        header = _createVNode("div", extraProps, [_createVNode("div", {
          "class": `${preCls}_title`
        }, [title])]);
      }

      return header;
    });
    const footerRef = computed(() => {
      const footer = getComponent(vm, 'footer');
      if (!footer) return undefined;
      return _createVNode("div", {
        "class": `${preCls}_footer`
      }, [footer]);
    });
    return () => {
      if (!isMounted.value) return;
      const {
        mask: hasMask,
        to,
        visible,
        width
      } = props;

      const body = _createVNode("div", {
        "class": `${preCls}_body`
      }, [getSlot(vm)]);

      const mask = hasMask ? _withDirectives(_createVNode("div", {
        "class": `${preCls}_mask`,
        "onClick": onMaskClick
      }, null), [[_vShow, visible]]) : undefined;
      const clazz = [preCls, {
        [`${preCls}-open`]: visible,
        [`${preCls}-glass`]: visible
      }];
      return _createVNode(Teleport, {
        "to": to
      }, {
        default: () => [_createVNode("div", _mergeProps({
          "class": clazz
        }, attrs), [_createVNode(Transition, {
          "name": 'fade'
        }, _isSlot(mask) ? mask : {
          default: () => [mask]
        }), _createVNode("div", {
          "class": `${preCls}_wrapper`,
          "style": {
            width: width + 'px'
          }
        }, [headerRef.value, body, footerRef.value])])]
      });
    };
  }

});

Drawer.install = app => {
  app.component(Drawer.name, Drawer);
};

export default Drawer;