import { gzipAsync } from "../../sync/entity/zlib";
import { eg } from "../edit-global";
const history = {} as Record<string, string>;

export const diffLocal = (ws: any, msg: any) => {
  return new Promise<void>((resolve) => {
    const diff_local = Uint8Array.from(
      msg.diff_local.split(",").map((x: any) => parseInt(x, 10))
    );
    let doc = null as unknown as Y.Doc;
    let wss: Set<any> = null as any;
    let um: Y.UndoManager = null as any;
    if (msg.mode === "page") {
      doc = eg.edit.page[msg.id].doc as any;
      wss = eg.edit.page[msg.id].ws;
      um = eg.edit.page[msg.id].undoManager;
    } else if (msg.mode === "comp") {
      doc = eg.edit.comp[msg.id].doc as any;
      wss = eg.edit.comp[msg.id].ws;
      um = eg.edit.comp[msg.id].undoManager;
    } else if (msg.mode === "site") {
      doc = eg.edit.site[msg.id].doc as any;
      wss = eg.edit.site[msg.id].ws;
      um = eg.edit.site[msg.id].undoManager;
    }

    if (doc && wss) {
      Y.applyUpdate(doc, diff_local);

      if (msg.mode === "page") {
        clearTimeout(eg.edit.page[msg.id].saveTimeout);
        eg.edit.page[msg.id].saveTimeout = setTimeout(async () => {
          if (msg.id) {
            const page = eg.edit.page[msg.id].doc.getMap("map").toJSON();
            try {
              const id = msg.id;
              let mode = "create" as "create" | "update";
              const cur = Math.round(Date.now() / 5000) + "";
              if (history[id] && history[id] === cur) {
                mode = "update";
              }
              history[id] = cur;
              if (mode === "create") {
                await _db.page_history.create({
                  data: {
                    id_page: id,
                    content_tree: await gzipAsync(
                      JSON.stringify(page.content_tree)
                    ),
                    ts: history[id],
                  },
                });
              } else {
                await _db.page_history.updateMany({
                  data: {
                    content_tree: await gzipAsync(
                      JSON.stringify(page.content_tree)
                    ),
                  },
                  where: {
                    id_page: id,
                    ts: history[id],
                  },
                });
              }

              await _db.page.update({
                where: { id: page.id },
                data: {
                  content_tree: page.content_tree,
                  updated_at: new Date(),
                },
              });
              resolve();
            } catch (e) {
              console.error(e);
              console.error({
                ...page,
                updated_at: new Date(),
              });
            }
          }
        }, 1500);
      } else if (msg.mode === "comp") {
        clearTimeout(eg.edit.comp[msg.id].saveTimeout);
        eg.edit.comp[msg.id].saveTimeout = setTimeout(async () => {
          const comp = eg.edit.comp[msg.id].doc.getMap("map").toJSON();
          await _db.component.update({
            where: {
              id: msg.id,
            },
            data: {
              name: comp.name,
              content_tree: comp.content_tree,
              updated_at: new Date(),
            },
          });
        }, 1500);
      } else if (msg.mode === "site") {
        clearTimeout(eg.edit.site[msg.id].saveTimeout);
        eg.edit.site[msg.id].saveTimeout = setTimeout(async () => {
          const site = eg.edit.site[msg.id].doc.getMap("site").toJSON();
          delete site.page;
          await _db.site.update({
            where: {
              id: msg.id,
            },
            data: {
              ...site,
            },
          });
        }, 1500);
      }
    }
  });
};
