import { defineStore } from "pinia";
import { AlignEnum } from "@/enum/alignEnum";
import { LayerEnum } from "@/enum/layerEnum";
import { useProjectStore } from "@/store/modules/project";
import { cloneDeep } from "lodash";
import { CustomElement } from "#/project";
import { uuid } from "@/utils";
import { calcComboInfo } from "@/utils/calc";
// import { recoverRecord } from "@/utils/recover";

// type RecordItem = {
//   info: Record<string, any>;
//   type: "add" | "update" | "delete" | "init";
//   snapshot: ProjectInfo;
// };
type ActionState = {
  // 操作记录--最大记录10条
  records: string[];
  // 当前操作索引
  activeIndex: number;
  appKey: number;
  copyCache: any;
};
export const useAcionStore = defineStore({
  id: "action",
  state(): ActionState {
    return {
      records: [],
      activeIndex: -1,
      appKey: 0,
      copyCache: null,
    };
  },
  getters: {
    projectStore: () => useProjectStore(),
    undoDisabled: (state) => state.activeIndex <= 0,
    redoDisabled: (state) => state.activeIndex === state.records.length - 1,
  },
  actions: {
    initRecord() {
      this.records = [JSON.stringify(this.projectStore.projectInfo)];
      this.activeIndex = 0;
    },
    // addRecord({type, info }: RecordItem & { snapshot?: ProjectInfo}) {
    addRecord() {
      // 新增如果当前索引不是最后一条, 覆盖后面的记录
      if (this.activeIndex < this.records.length - 1) {
        this.records.splice(this.activeIndex + 1, this.records.length);
      }

      this.records.push(JSON.stringify(this.projectStore.projectInfo));

      // 新增如果超过10条记录，删除最早的一条
      if (this.records.length > 10) {
        this.records.shift();
        this.activeIndex--;
      }

      this.activeIndex = this.records.length - 1;
    },
    /* 撤销 */
    actionUndo() {
      if (this.activeIndex <= 0) return;
      --this.activeIndex;
      const projectInfo = JSON.parse(this.records[this.activeIndex]);
      this.projectStore.updateProjectInfo(projectInfo);
      this.appKey++;
    },
    /* 重做 */
    actionRedo() {
      ++this.activeIndex;
      const projectInfo = JSON.parse(this.records[this.activeIndex]);
      this.projectStore.updateProjectInfo(projectInfo);
      this.appKey++;
    },
    actionClear() {},
    /* 对齐 */
    actionAlign(type: AlignEnum) {
      const activeElements = this.projectStore.currentSelectedElements;
      switch (type) {
        case AlignEnum.Bottom: {
          const maxY = Math.max(
            ...activeElements.map(
              (item) => item.container.props.y + item.container.props.height
            )
          );
          activeElements.forEach((item) => {
            this.projectStore.updateElement(
              item.key,
              "container.props.y",
              maxY - item.container.props.height
            );
          });
          break;
        }
        case AlignEnum.HorizontalCenter: {
          const maxX = Math.max(
            ...activeElements.map(
              (item) => item.container.props.x + item.container.props.width
            )
          );
          const minX = Math.min(
            ...activeElements.map((item) => item.container.props.x)
          );
          const centerX = minX + (maxX - minX) / 2;
          activeElements.forEach((item) => {
            this.projectStore.updateElement(
              item.key,
              "container.props.x",
              centerX - item.container.props.width / 2
            );
          });
          break;
        }
        case AlignEnum.VerticalCenter: {
          const maxY = Math.max(
            ...activeElements.map(
              (item) => item.container.props.y + item.container.props.height
            )
          );
          const minY = Math.min(
            ...activeElements.map((item) => item.container.props.y)
          );
          const centerY = minY + (maxY - minY) / 2;
          activeElements.forEach((item) => {
            this.projectStore.updateElement(
              item.key,
              "container.props.y",
              centerY - item.container.props.height / 2
            );
          });
          break;
        }
        case AlignEnum.Left: {
          const minX = Math.min(
            ...activeElements.map((item) => item.container.props.x)
          );
          activeElements.forEach((item) => {
            this.projectStore.updateElement(
              item.key,
              "container.props.x",
              minX
            );
          });
          break;
        }
        case AlignEnum.Right: {
          const maxX = Math.max(
            ...activeElements.map(
              (item) => item.container.props.x + item.container.props.width
            )
          );
          activeElements.forEach((item) => {
            this.projectStore.updateElement(
              item.key,
              "container.props.x",
              maxX - item.container.props.width
            );
          });
          break;
        }
        case AlignEnum.Top: {
          const minY = Math.min(
            ...activeElements.map((item) => item.container.props.y)
          );
          activeElements.forEach((item) => {
            this.projectStore.updateElement(
              item.key,
              "container.props.y",
              minY
            );
          });
          break;
        }
        default:
      }
      this.addRecord();
    },
    /* 图层调整 */
    actionLayer(type: LayerEnum) {
      const activeElements = this.projectStore.currentSelectedElements;
      const elements = cloneDeep(
        this.projectStore.elements.sort((a, b) => a.zIndex - b.zIndex)
      ) as CustomElement[];

      switch (type) {
        case LayerEnum.UP: {
          activeElements.forEach((item) => {
            const index = elements.findIndex(
              (element) => element.key === item.key
            );
            if (item.zIndex === elements.length) return;
            elements.splice(index, 1);
            elements.splice(index + 1, 0, { ...item });
          });
          elements.forEach((item, index) => {
            item.zIndex = index + 1;
          });
          elements.forEach((item) => {
            this.projectStore.updateElement(item.key, "zIndex", item.zIndex);
          });
          break;
        }
        case LayerEnum.DOWN: {
          activeElements.forEach((item) => {
            const index = elements.findIndex(
              (element) => element.key === item.key
            );
            if (item.zIndex === 1) return;
            elements.splice(index, 1);
            elements.splice(index - 1, 0, { ...item });
          });
          elements.forEach((item, index) => {
            item.zIndex = index + 1;
          });
          elements.forEach((item) => {
            this.projectStore.updateElement(item.key, "zIndex", item.zIndex);
          });
          break;
        }
        case LayerEnum.TOP: {
          activeElements.forEach((item) => {
            const index = elements.findIndex(
              (element) => element.key === item.key
            );
            if (item.zIndex === elements.length) return;
            elements.splice(index, 1);
            elements.push({ ...item });
          });
          elements.forEach((item, index) => {
            item.zIndex = index + 1;
          });
          elements.forEach((item) => {
            this.projectStore.updateElement(item.key, "zIndex", item.zIndex);
          });
          break;
        }
        case LayerEnum.BOTTOM: {
          activeElements.forEach((item) => {
            const index = elements.findIndex(
              (element) => element.key === item.key
            );
            if (item.zIndex === 1) return;
            elements.splice(index, 1);
            elements.unshift({ ...item });
          });
          elements.forEach((item, index) => {
            item.zIndex = index + 1;
          });
          elements.forEach((item) => {
            this.projectStore.updateElement(item.key, "zIndex", item.zIndex);
          });
          break;
        }
      }
      this.addRecord();
    },
    /* 添加组合 */
    actionGroup() {
      const elements = this.projectStore.currentSelectedElements;
      const key = uuid();
      // 1、移除元素
      elements.forEach((element) => {
        this.projectStore.removeElement(element.key);
      });
      const { minX, minY, maxX, maxY, maxZIndex } = calcComboInfo(elements);
      const groupIndex = this.projectStore.elements.filter((item) => item.componentType === "group").length + 1;
      // 重新计算子元素位置
      elements.forEach((item) => {
        item.container.props.x -= minX;
        item.container.props.y -= minY;
        item.parentKey = key;
      });
      const group: CustomElement = {
        key,
        name: "组合" + groupIndex,
        componentType: "group",
        visible: true,
        locked: false,
        zIndex: maxZIndex,
        container: {
          style: {},
          props: {
            width: maxX - minX,
            height: maxY - minY,
            x: minX,
            y: minY,
          },
        },
        children: elements,
        collapsed: false,
        events: [],
        animations: [],
        props: {}
      }
      // 2、添加组合元素
      this.projectStore.addElement(group);
    },
   /* 拆分组合元素 */
    actionUngroup() {
      const group = this.projectStore.currentSelectedElements[0];
      // 1、取出子元素
      const elements = group.children?.map((item) => {
        // 2、计算子元素位置
        item.container.props.x += group.container.props.x;
        item.container.props.y += group.container.props.y;
        delete item.parentKey;
        return item;
      });
    
      // 3、移除组
      this.projectStore.removeElement(group.key);
      // 4、添加子元素
      elements?.forEach((item) => {
        this.projectStore.addElement(item, undefined, true);
      });
    },
    /* 复制 */
    actionCopy() {
      const elements = this.projectStore.currentSelectedElements;
      this.copyCache = JSON.stringify(elements);
    },
    /* 粘贴 */
    actionPaste() {
      try {
        const elements = JSON.parse(this.copyCache);
        const offsetX = 10;
        const offsetY = 10;
        elements.forEach((element: CustomElement) => {
          element.key = uuid();
          element.container.props.x += offsetX;
          element.container.props.y += offsetY;
          this.projectStore.addElement(element);
        });
      } catch (error) {
        console.log(error);
      }
    }
  },
});
