import { ModuleControl } from "queenjs";
import { EditorModule } from "../../module";
import { DesignComp } from "../../objects/DesignTemp/DesignComp";
import { Matrix } from "./Matrix";

export class GroupActionCtrl extends ModuleControl<EditorModule> {
  // init() {
  //   document.body.addEventListener("keydown", this.enableGroupMode);
  // }
  // enableGroupMode = (event: KeyboardEvent) => {
  //   if (event.key === "Control" && !this.store.groupModeStatus) {
  //     this.actions.enableGroupMode();
  //     document.body.addEventListener("keyup", this.disableGroupMode);
  //   }
  // };
  // disableGroupMode = (event: KeyboardEvent) => {
  //   if (event.key === "Control") {
  //     this.actions.disableGroupMode();
  //     document.body.removeEventListener("keyup", this.disableGroupMode);
  //   }
  // };
  // destroy() {
  //   document.body.removeEventListener("keydown", this.enableGroupMode);
  // }

  async combineGroup() {
    const { helper, store } = this;
    const { groupIds } = store;
    if (groupIds.length < 2) return;
    const compsRect: Record<
      string,
      { t: number; l: number; r: number; b: number }
    > = {};
    const parentComp = helper.findParentComp(groupIds[0]) as DesignComp;
    const parentRect = parentComp.$el.getBoundingClientRect();
    groupIds.forEach((id) => {
      const comp = helper.findComp(id) as DesignComp;
      const itemRect = comp.$el.getBoundingClientRect();
      compsRect[id] = {
        t: itemRect.top - parentRect.top,
        l: itemRect.left - parentRect.left,
        r: itemRect.right - parentRect.left,
        b: itemRect.bottom - parentRect.top,
      };
    });

    const confVals = Object.values(compsRect);
    const groupConf = {
      t: Math.min(...confVals.map((d) => d.t)),
      l: Math.min(...confVals.map((d) => d.l)),
      r: Math.max(...confVals.map((d) => d.r)),
      b: Math.max(...confVals.map((d) => d.b)),
    };

    const groupId = await this.store.insertCompContainer("Group", parentComp);

    const groupComp = helper.findComp(groupId) as DesignComp;

    groupComp.layout = {
      size: [
        helper.pxToDesignSize(groupConf.r - groupConf.l),
        helper.pxToDesignSize(groupConf.b - groupConf.t),
      ],
      position: "absolute",
      transform: {
        x: helper.pxToDesignSize(groupConf.l),
        y: helper.pxToDesignSize(groupConf.t),
      },
    };

    groupIds.forEach((id) => {
      const comp = helper.findComp(id) as DesignComp;
      comp.layout.transform || (comp.layout.transform = {});
      comp.layout.transform.x =
        (comp.layout.transform.x || 0) - (groupComp.layout.transform?.x || 0);

      comp.layout.transform.y =
        (comp.layout.transform.y || 0) - (groupComp.layout.transform?.y || 0);
    });

    groupComp.children.default = parentComp.children.default?.filter((d) =>
      groupIds.includes(d)
    );
    parentComp.children.default = parentComp.children.default?.filter(
      (d) => !groupIds.includes(d)
    );

    return groupId;
  }

  async cancelGroup(groupComp: DesignComp) {
    const { helper } = this;
    const groupChildIds = groupComp.children.default as string[];

    const parentComp = helper.findParentComp(groupComp.id) as DesignComp;

    const parentMatrix = new Matrix();

    groupChildIds.forEach((id) => {
      const comp = helper.findComp(id) as DesignComp;

      parentMatrix.setFormDiv(groupComp.$el);
      const originArr = window
        .getComputedStyle(groupComp.$el)
        .transformOrigin.split(" ")
        .map((v) => parseFloat(v));

      const porigin = new Matrix();
      porigin.translate(originArr[0], originArr[1]);
      const invOrigin = new Matrix();
      invOrigin.translate(-originArr[0], -originArr[1]);

      const childOrigArr = window
        .getComputedStyle(comp.$el)
        .transformOrigin.split(" ")
        .map((v) => parseFloat(v));
      const corigin = new Matrix();
      corigin.translate(childOrigArr[0], childOrigArr[1]);
      const cinvOrigin = new Matrix();
      cinvOrigin.translate(-childOrigArr[0], -childOrigArr[1]);

      const childMatrix = new Matrix();
      childMatrix.setFormDiv(comp.$el);

      const result = cinvOrigin
        .multipy(porigin)
        .multipy(parentMatrix)
        .multipy(invOrigin)
        .multipy(corigin)
        .multipy(childMatrix);

      comp.layout.transform || (comp.layout.transform = {});
      comp.layout.transform.x = helper.pxToDesignSize(result.getX());
      comp.layout.transform.y = helper.pxToDesignSize(result.getY());
      comp.layout.transform.s = result.getScale();
      comp.layout.transform.r = result.getRotate();
    });

    const childIds = [...(parentComp.children.default as string[])];

    const groupIndex = childIds.findIndex((id) => groupComp.id === id);
    childIds.splice(groupIndex, 1, ...groupChildIds);

    parentComp.children.default = childIds;
  }
}
