<script setup lang="tsx">
import { dialogKeyType, DialogState, dialogStore } from "./index";
import { ElButton } from "element-plus";
import XEUtils from "xe-utils";
import sleep from "@/utils/sleep";
import { nextTick, renderSlot } from "vue";

function next(item: DialogState, data: any) {
  if (item.closeValue === "confirm") {
    item.resolve(data);
  } else {
    item.reject({ value: item.closeValue, data });
  }
  item.visible = false;
}

async function handleCancel(item: DialogState, emits = false, value = null) {
  if (emits) {
    item.closeValue = "cancel";
    next(item, value);
    return;
  }
  try {
    const fn = item.componentRef?.cancel ?? XEUtils.noop;
    const data = await fn();
    item.closeValue = "cancel";
    next(item, data);
  } catch {}
}

async function handleConfirm(item: DialogState, emits = false, value = null) {
  if (emits) {
    item.closeValue = "confirm";
    next(item, value);
    return;
  }
  const fn = item.componentRef?.confirm ?? XEUtils.noop;
  try {
    const data = await fn();
    item.closeValue = "confirm";
    next(item, data);
  } catch {}
}

async function closed(item: DialogState, index: number) {
  item.reject({ value: item.closeValue, data: null });
  await nextTick();
  await sleep();
  dialogStore.value.splice(index, 1);
}

function setRef(el, item) {
  item.componentRef = el;
}

const ConfigProvider = defineComponent({
  props: {
    item: Object,
  },
  setup(props, { slots }) {
    provide(dialogKeyType, props.item);
    return () => renderSlot(slots, "default");
  },
});
</script>

<template>
  <el-dialog
    v-for="(item, index) in dialogStore"
    :key="`Cy-dialog_${item.dialogKey}`"
    :style="{ '--el-dialog-border-radius': '14px' }"
    v-model="item.visible"
    draggable
    v-bind="item.dialogProps"
    @closed="closed(item, index)"
  >
    <ConfigProvider :item="item">
      <component
        :is="item.component"
        :ref="el => setRef(el, item)"
        v-bind="item.params"
        @cyDialogCancel="
          (value: any, isEmits = true) => handleCancel(item, isEmits, value)
        "
        @cyDialogConfirm="
          (value: any, isEmits = true) => handleConfirm(item, isEmits, value)
        "
        :cyDialog="item"
      />
    </ConfigProvider>
    <template #footer v-if="item.showFooter">
      <el-button
        size="default"
        v-if="item.showCancel"
        @click="handleCancel(item)"
      >
        {{ item.cancelText || "取消" }}
      </el-button>

      <el-button
        v-if="item.showConfirm"
        type="primary"
        size="default"
        color="hsl(240 5.9% 10%)"
        @click="handleConfirm(item)"
      >
        {{ item.confirmText || "确认" }}
      </el-button>
    </template>
  </el-dialog>
</template>

<style lang="scss">
.el-dialog.is-fullscreen {
  display: flex;
  flex-direction: column;

  .el-dialog__body {
    flex: 1;
    height: 0;
  }
}
</style>
