<template>
  <Modal v-bind="getBindValue" @cancel="handleCancel">
    <!--自定义关闭-->
    <template #closeIcon v-if="!$slots.closeIcon">
      <template v-if="canFullscreen">
        <a-tooltip title="还原" placement="bottom" v-if="fullScreenRef" class="mr-1">
          <FullscreenExitOutlined role="full" @click="handleFullScreen" />
        </a-tooltip>
        <a-tooltip v-else title="最大化" placement="bottom" class="mr-1">
          <FullscreenOutlined role="close" @click="handleFullScreen" />
        </a-tooltip>
      </template>
      <a-tooltip title="关闭" placement="bottom">
        <CloseOutlined @click="handleCancel" class="ml-4" />
      </a-tooltip>
    </template>

    <!--内容区域-->
    <slot name="default"></slot>

    <!--底部插槽-->
    <template v-if="!$slots.footer" #footer>
      <a-space>
        <slot name="prefixFooter"></slot>
        <a-button v-bind="cancelButtonProps" @click="handleCancel" v-if="getProps.showCancelBtn">{{
          getProps.cancelText
        }}</a-button>
        <slot name="centerFooter"></slot>
        <a-button
          :type="getProps.okType"
          v-bind="okButtonProps"
          :loading="subLoading"
          @click="handleSubmit"
          v-if="getProps.showOkBtn"
          >{{ getProps.okText }}
        </a-button>
        <slot name="suffixFooter"></slot>
      </a-space>
    </template>

    <template v-else #footer>
      <slot name="action"></slot>
    </template>

    <template #[item]="data" v-for="item in Object.keys(omit($slots, 'default'))">
      <slot :name="item" v-bind="data || {}"></slot>
    </template>
  </Modal>
</template>
<script lang="ts" setup>
  import { getCurrentInstance, ref, nextTick, unref, computed, useAttrs } from 'vue';
  import { basicProps } from './props';
  import startDrag from '@/utils/Drag';
  import { deepMerge } from '@/utils';
  import Modal from './components/Modal';
  import { ModalMethods } from './type';
  import { omit, uniqueId } from 'lodash-es';
  import { FullscreenExitOutlined, FullscreenOutlined, CloseOutlined } from '@ant-design/icons-vue';

  const attrs = useAttrs();
  const props = defineProps({ ...basicProps });
  const emit = defineEmits(['cancel', 'ok', 'register']);

  const propsRef = ref({});
  const isModal = ref(false);
  const fullScreenRef = ref(false);
  const subLoading = ref(false);

  const basicModalId = uniqueId('basic-modal-');
  const basicModalBarId = uniqueId('basic-modal-bar-');

  const getProps = computed(() => {
    return { ...props, ...(unref(propsRef) as any) };
  });

  async function setProps(modalProps): Promise<void> {
    propsRef.value = deepMerge(unref(propsRef) || ({} as any), modalProps);
  }

  const getWrapClassName = computed(() => {
    const wrapClassName = props.wrapClassName;
    return unref(fullScreenRef)
      ? `fullscreen-modal ${wrapClassName}`
      : `basic-modal ${wrapClassName}`;
  });

  const getBindValue = computed(() => {
    return {
      ...attrs,
      ...unref(getProps),
      ...unref(propsRef),
      visible: unref(isModal),
      wrapClassName: unref(getWrapClassName),
    };
  });

  function setSubLoading(status: boolean) {
    subLoading.value = status;
  }

  function openModal() {
    isModal.value = true;
    if (!unref(getProps).isDraggable) return;
    nextTick(() => {
      const oBox = document.getElementById(basicModalId);
      const oBar = document.getElementById(basicModalBarId);
      if (!oBox || !oBar) {
        console.warn('not found modal');
        return;
      }
      startDrag(oBar, { target: oBox });
    });
  }

  function closeModal() {
    isModal.value = false;
    subLoading.value = false;
    emit('cancel');
  }

  function handleSubmit() {
    subLoading.value = true;
    emit('ok');
  }

  function handleCancel(e) {
    isModal.value = false;
    emit('cancel', e);
  }

  function handleFullScreen(e: Event) {
    e && e.stopPropagation();
    fullScreenRef.value = !unref(fullScreenRef);
  }

  const modalMethods: ModalMethods = {
    setProps,
    openModal,
    closeModal,
    setSubLoading,
  };

  const instance = getCurrentInstance();
  if (instance) {
    emit('register', modalMethods);
  }

  defineExpose({
    openModal,
    closeModal,
    setProps,
    setSubLoading,
    handleSubmit,
  });
</script>

<style lang="less" scoped>
  .cursor-move {
    cursor: move;
  }
  .basicModal :deep(.ant-modal .ant-modal-content .ant-modal-close .ant-modal-close-x) {
    width: auto;
  }
</style>
