<template>
  <div class="lj-grid-layout" :style="!setting ? style : {}">
    <slot name="default" :style="style" :cols="cols" :breakpoint="breakPoint" :gridCols="gridCols"></slot>
  </div>
</template>

<script setup lang="ts" name="Grid">
import {
  ref,
  watch,
  useSlots,
  computed,
  provide,
  inject,
  onBeforeMount,
  onMounted,
  onUnmounted,
  onDeactivated,
  onActivated,
  VNodeArrayChildren,
  VNode,
  nextTick
} from "vue";
import type { BreakPoint } from "./interface/index";
import mittBus from "@/utils/mittBus";
import { MittEnum } from "@/enums/mittEnum";
import { useGlobalStore } from "@/stores/modules/global";
import { FORM_LINE_HEIGHT } from "@/config";

type Props = {
  /**
   * @description 每行分几个span
   */
  cols?: number | Record<BreakPoint, number>;
  /**
   * @description 是否展开，true: 是
   */
  collapsed?: boolean;
  /**
   * @description 是否正在编辑
   */
  setting?: boolean;
  /**
   * @description 展示的行数
   */
  collapsedRows?: number;
  /**
   * @description 间距
   */
  gap?: [number, number] | number;
  target?: any;
};

const props = withDefaults(defineProps<Props>(), {
  cols: () => ({ xs: 1, sm: 2, md: 3, lg: 4, xl: 5 }),
  collapsed: false,
  setting: false,
  collapsedRows: 1,
  gap: 0
});
const { assemblySize } = useGlobalStore();

onBeforeMount(() => props.collapsed && findIndex());
onMounted(() => {
  // onBeforeMount(() => {
  // console.log("grid reset onmount:>> ", props.target, props.collapsed);
  // props.collapsed && findIndex();
  resize({ target: { innerWidth: window.innerWidth } } as unknown as UIEvent);
  window.addEventListener("resize", resize);
});
onActivated(() => {
  resize({ target: { innerWidth: window.innerWidth } } as unknown as UIEvent);
  window.addEventListener("resize", resize);
});
onUnmounted(() => {
  window.removeEventListener("resize", resize);
});
onDeactivated(() => {
  window.removeEventListener("resize", resize);
});

const breakPointUpdate = inject("breakPointUpdate", (data: any, target: string) => {});

// 监听屏幕变化
const resize = (e: UIEvent, callback?: any) => {
  nextTick(() => {
    let width = (e.target as Window).innerWidth;
    // console.log("grid resize props.target :>> ", props.target);
    if (props.target) {
      let _target = document.getElementById(props.target) as HTMLElement;
      _target && (width = _target.offsetWidth);
      // console.log("grid resize props.target width:>> ", props.target, width);
    }
    switch (!!width) {
      case width < 768:
        breakPoint.value = "xs";
        break;
      case width >= 768 && width < 992:
        breakPoint.value = "sm";
        break;
      case width >= 992 && width < 1380:
        breakPoint.value = "md";
        break;
      case width >= 1380 && width < 1920:
        breakPoint.value = "lg";
        break;
      case width >= 1920:
        breakPoint.value = "xl";
        break;
    }
    // console.log("grid resize breakPoint.value :>> ", breakPoint.value);
    breakPointUpdate(breakPoint.value, props.target);
    callback && callback();
  });
};

/**
 * @description 监听框架属性变化
 */
mittBus.on(MittEnum.FoldLayoutChange, layout => {
  console.log("MittEnum.FoldLayoutChange grid:>> ", MittEnum.FoldLayoutChange, layout);
  resize({ target: { innerWidth: window.innerWidth } } as unknown as UIEvent);
});

// 注入 gap 间距
provide("gap", Array.isArray(props.gap) ? props.gap[0] : props.gap);

// 注入响应式断点
const breakPoint = ref<BreakPoint>("xl");
provide("breakPoint", breakPoint);

// 注入要开始折叠的 index
const hiddenIndex = ref(-1);
provide("shouldHiddenIndex", hiddenIndex);

// 注入 cols
const gridCols = computed(() => {
  if (typeof props.cols === "object") return props.cols[breakPoint.value] ?? props.cols;
  return props.cols;
});
provide("cols", gridCols);

// 寻找需要开始折叠的字段 index
const slots = useSlots();

const findIndex = () => {
  // setTimeout(() => {
  nextTick(() => {
    let fields: VNodeArrayChildren = [];
    let suffix: VNode | null = null;

    let _slots = slots.default!();
    _slots.forEach((slot: any) => {
      // suffix
      if (typeof slot.type === "object" && slot.type.name === "GridItem" && slot.props?.suffix !== undefined) suffix = slot;
      // slot children
      if (typeof slot.type === "symbol" && Array.isArray(slot.children)) fields.push(...slot.children);
    });
    // 计算 suffix 所占用的列
    let suffixCols = 0;
    if (suffix) {
      suffixCols =
        ((suffix as VNode).props![breakPoint.value]?.span ?? (suffix as VNode).props?.span ?? 1) +
        ((suffix as VNode).props![breakPoint.value]?.offset ?? (suffix as VNode).props?.offset ?? 0);
      // if (!props.collapsed) {
      //   suffixCols =
      //     ((suffix as VNode).props![breakPoint.value]?.span ?? (suffix as VNode).props?.span ?? 1) +
      //     ((suffix as VNode).props![breakPoint.value]?.offset ?? (suffix as VNode).props?.offset ?? 0);
      // } else {
      //   suffixCols = 1 + ((suffix as VNode).props![breakPoint.value]?.offset ?? (suffix as VNode).props?.offset ?? 0);
      // }
    }
    try {
      let find = false;
      fields.reduce((prev = 0, current, index) => {
        prev +=
          ((current as VNode)!.props![breakPoint.value]?.span ?? (current as VNode)!.props?.span ?? 1) +
          ((current as VNode)!.props![breakPoint.value]?.offset ?? (current as VNode)!.props?.offset ?? 0);
        if (Number(prev) > props.collapsedRows * gridCols.value - suffixCols) {
          // if (Number(prev) > props.collapsedRows * gridCols.value) {
          hiddenIndex.value = index;
          find = true;
          throw "find it";
        }
        return prev;
      }, 0);
      if (!find) hiddenIndex.value = -1;
    } catch (e) {
      // console.warn(e);
    }
    // }, 1);
  });
};

// 断点变化时 执行 findIndex
watch(
  () => breakPoint.value,
  () => {
    if (props.collapsed) findIndex();
  }
);

// 监听 collapsed
watch(
  () => props.collapsed,
  value => {
    if (value) return findIndex();
    hiddenIndex.value = -1;
  }
);

// 设置间距
const gridGap = computed(() => {
  if (typeof props.gap === "number") return `${props.gap}px`;
  if (Array.isArray(props.gap)) return `${props.gap[1]}px ${props.gap[0]}px`;
  return "unset";
});

// 设置 style
const style = computed(() => {
  return {
    display: "grid",
    gridGap: gridGap.value,
    gridTemplateColumns: `repeat(${gridCols.value}, minmax(0, 1fr))`,
    gridAutoRows: `minmax(${FORM_LINE_HEIGHT[assemblySize]}px, auto)`
    // gridAutoRows: `${FORM_LINE_HEIGHT[assemblySize]}px`
  };
});

defineExpose({ breakPoint, resize });
</script>
