import { Dict_Imgs } from "@/dict";
import { eachValuesAndPathsDeep } from "@/utils";
import { PageListController } from "@queenjs/controllers";
import { set } from "lodash";
import { nanoid } from "nanoid";
import { Exception, ModuleControl } from "queenjs";
import { markRaw, reactive } from "vue";
import * as basicUI from "../../components/CompUI/basicUI";
import * as customUI from "../../components/CompUI/customUI";
import {
  addCacheToMap,
  createCompId,
} from "../../components/CompUI/defines/createCompId";
import { EditorModule } from "../../module";
import { DesignComp } from "../../objects/DesignTemp/DesignComp";
import { ICompKeys } from "../../typings";

interface CompItem {
  compKey: string;
  compType: "basic" | "senior" | "user";
  name: string;
  thumbnail: string;
  Component: any;
  Form: any;
  createComp: (...args: any) => DesignComp;
}

export class CompUICtrl extends ModuleControl<EditorModule> {
  state = reactive({
    components: new Map<string, CompItem>(),
  });
  init() {
    this.state.components.clear();
    this.initDefaultUI();
    if (this.store.isEditMode) {
      this.initUserUI();
    }
  }
  private initDefaultUI() {
    Object.entries({ ...basicUI, ...customUI }).forEach(([key, value]) => {
      this.state.components.set(key, {
        compKey: key,
        compType: (basicUI as any)[key] ? "basic" : "senior",
        name: value.options.name,
        thumbnail: value.options.thumbnail,
        Component: markRaw(value.Component),
        Form: markRaw(value.Form),
        createComp: value.createComp,
      });
    });
  }
  private async initUserUI() {
    const listCtrl = new PageListController<
      { _id: string; title: string; thumbnail: string },
      any
    >(this.module.config.httpConfig);
    listCtrl.setCrudPrefix("/frame");
    listCtrl.state.size = 999;
    await listCtrl.loadPage(1);

    listCtrl.state.list.forEach((d) => {
      const compItem: CompItem = {
        compKey: d._id,
        compType: "user",
        name: d.title,
        thumbnail: d.thumbnail || Dict_Imgs.Default,
        Component: markRaw(basicUI.Container.Component),
        Form: markRaw(basicUI.Container.Form),
        createComp: basicUI.Container.createComp,
      };
      this.state.components.set(d._id, compItem);
    });
  }

  async initUserCompDetail(compKey: string) {
    const { compMap } = this.store.designData;
    const { result } = await this.https.getCompDetail(compKey);
    const idMap = new Map<string, string>();
    const nextCompMap: Record<string, DesignComp> = {};
    Object.entries(result.compMap as Record<string, DesignComp>).forEach(
      ([key, comp]) => {
        if (key === "root") {
          idMap.set(key, nanoid());
          comp.title = result.title;
          comp.thumbnail = result.thumbnail;
        }
        const id = idMap.get(key) || nanoid();
        idMap.set(key, id);
        comp.id = id;
        eachValuesAndPathsDeep(
          comp.children,
          (v) => typeof v === "string",
          (v, paths) => {
            const id = idMap.get(v) || nanoid();
            idMap.set(v, id);
            set(comp.children, paths, id);
          }
        );
        nextCompMap[id] = new DesignComp(comp);
      }
    );
    Object.assign(compMap, nextCompMap);
    return nextCompMap[idMap.get("root") as string];
  }

  async createCompId(compKey: ICompKeys) {
    let compId = "";
    const compItem = this.state.components.get(compKey);
    if (!compItem) throw Exception.error("无效的组件");
    if (compItem.compType === "user") {
      const comp = await this.initUserCompDetail(compKey);
      compId = comp.id;
    } else {
      compId = createCompId(compKey);
      addCacheToMap(this.store.designData.compMap);
    }
    return compId;
  }
}
