import { defineComponent, ref, watch, nextTick, computed, createVNode, Teleport, Transition, withDirectives, vShow } from 'vue';
import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
import { isNumber } from 'lodash-es';
import { useStorage } from '@vueuse/core';
import getPrefixCls from '../_util/getPrefixCls';
import { CloseOutlined } from '../icon';
import { useTheme } from '../_theme/useTheme';
import { useConfig } from '../config-provider';
import { getPrefixStorage, getStorage } from '../_util/storage';
import PopupManager from '../_util/popupManager';
import { floatPaneProps } from './props';
import { useDrag } from './useDrag';

function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
const prefixCls = getPrefixCls('float-pane');
const UPDATE_VISIBLE_EVENT = 'update:visible';
const AFTER_ENTER_EVENT = 'after-enter';
const AFTER_LEAVE_EVENT = 'after-leave';
const FloatPane = defineComponent({
  name: 'FFloatPane',
  props: floatPaneProps,
  emits: [UPDATE_VISIBLE_EVENT, AFTER_ENTER_EVENT, AFTER_LEAVE_EVENT],
  setup(props, ctx) {
    useTheme();
    const innerVisible = ref(false);
    const domRef = ref(null);
    const domHeaderRef = ref(null);
    const zIndex = ref(props.zIndex || PopupManager.nextZIndex());
    watch(() => props.visible, () => {
      if (props.visible) {
        zIndex.value = props.zIndex || PopupManager.nextZIndex();
      }
      nextTick(() => {
        innerVisible.value = props.visible;
      });
    }, {
      immediate: true
    });
    const config = useConfig();
    const getContainer = computed(() => {
      var _config$getContainer;
      return props.getContainer || ((_config$getContainer = config.getContainer) === null || _config$getContainer === void 0 ? void 0 : _config$getContainer.value);
    });
    function handleCancel() {
      innerVisible.value = false;
      ctx.emit(UPDATE_VISIBLE_EVENT, false);
    }
    function handleTransitionAfterEnter(el) {
      ctx.emit(AFTER_ENTER_EVENT, el);
    }
    function handleTransitionAfterLeave(el) {
      ctx.emit(AFTER_LEAVE_EVENT, el);
    }
    const hasHeader = () => ctx.slots.title || props.title;
    const transform = props.cachePosition ? useStorage(getPrefixStorage(props.cachePositionKey || 'float-pane'), {
      offsetX: 0,
      offsetY: 0
    }, getStorage(props.cachePosition)) : ref({
      offsetX: 0,
      offsetY: 0
    });
    const styles = computed(() => {
      const {
        offsetX,
        offsetY
      } = transform.value;
      return _objectSpread(_objectSpread({
        zIndex: zIndex.value,
        width: isNumber(props.width) ? `${props.width}px` : props.width
      }, props.defaultPosition), {}, {
        transform: `translate(${offsetX}px, ${offsetY}px)`
      });
    });
    const {
      handleMouseDown,
      isDragging
    } = useDrag(transform, domRef, domHeaderRef, getContainer, props.defaultPosition);
    const handleDraggable = event => {
      if (props.draggable) {
        handleMouseDown(event);
      }
    };
    function getHeader() {
      var _ctx$slots$title, _ctx$slots;
      const closeJsx = createVNode("div", {
        "class": `${prefixCls}-close`,
        "onClick": handleCancel
      }, [createVNode(CloseOutlined, null, null)]);
      if (!hasHeader()) {
        return closeJsx;
      }
      const header = ((_ctx$slots$title = (_ctx$slots = ctx.slots).title) === null || _ctx$slots$title === void 0 ? void 0 : _ctx$slots$title.call(_ctx$slots)) || props.title;
      return createVNode("div", {
        "ref": domHeaderRef,
        "class": [`${prefixCls}-header`, isDragging.value && `${prefixCls}-header--dragging`],
        "onMousedown": handleDraggable
      }, [createVNode("div", null, [header]), closeJsx]);
    }
    const getBody = () => {
      var _ctx$slots$default, _ctx$slots2;
      return createVNode("div", {
        "class": `${prefixCls}-body`
      }, [(_ctx$slots$default = (_ctx$slots2 = ctx.slots).default) === null || _ctx$slots$default === void 0 ? void 0 : _ctx$slots$default.call(_ctx$slots2)]);
    };
    const showDom = computed(() => props.displayDirective === 'if' && innerVisible.value || props.displayDirective === 'show');
    const wrapperClass = computed(() => {
      return [`${prefixCls}-container`, props.contentClass].filter(Boolean);
    });
    ctx.expose({
      show() {
        innerVisible.value = true;
      },
      hide() {
        innerVisible.value = false;
      },
      resetPosition() {
        transform.value = {
          offsetX: 0,
          offsetY: 0
        };
      }
    });
    return () => {
      var _getContainer$value, _getContainer$value2;
      return createVNode(Teleport, {
        "disabled": !((_getContainer$value = getContainer.value) !== null && _getContainer$value !== void 0 && _getContainer$value.call(getContainer)),
        "to": (_getContainer$value2 = getContainer.value) === null || _getContainer$value2 === void 0 ? void 0 : _getContainer$value2.call(getContainer)
      }, {
        default: () => [createVNode("div", {
          "class": prefixCls
        }, [createVNode(Transition, {
          "name": `${prefixCls}-fade`,
          "onAfterEnter": handleTransitionAfterEnter,
          "onAfterLeave": handleTransitionAfterLeave
        }, {
          default: () => [showDom.value && withDirectives(createVNode("div", {
            "ref": domRef,
            "class": wrapperClass.value,
            "style": styles.value
          }, [getHeader(), getBody()]), [[vShow, innerVisible.value]])]
        })])]
      });
    };
  }
});

export { FloatPane as default };
