import { defineComponent, h } from "vue";
import { resolveView, viewPathToName } from "../lib/module";
const addedNames = new Set;
function isMicroMenu(m) {
  return Boolean(m.appKey && m.router);
}
function walk(nodes, out) {
  for (const n of nodes) {
    if (Number(n.type) === 1 && n.router)
      out.push(n);
    if (n.children?.length)
      walk(n.children, out);
  }
}
function missingView(shell, viewPath) {
  return defineComponent({
    name: "MissingViewPage",
    setup() {
      return () => h(shell.missing, { path: viewPath });
    }
  });
}
function routeNameOf(id) {
  return `menu-${id}`;
}
function buildRoute(item, shell) {
  const full = item.router;
  const childPath = full.replace(/^\//, "");
  let component;
  const componentName = viewPathToName(item.viewPath);
  const meta = {
    title: item.name,
    keepAlive: item.keepAlive !== false,
    viewPath: item.viewPath,
    perms: item.perms,
    componentName
  };
  if (isMicroMenu(item)) {
    component = shell.micro;
    meta.appKey = item.appKey;
    meta.componentName = `micro-${item.appKey}`;
    meta.keepAlive = false;
  } else if (item.viewPath) {
    const loader = resolveView(item.viewPath);
    component = loader || missingView(shell, item.viewPath);
  } else {
    component = missingView(shell, full);
  }
  return {
    path: childPath,
    name: routeNameOf(item.id),
    component,
    meta
  };
}
export async function ensureMenuRoutes(router, menus, shell) {
  const items = [];
  walk(menus, items);
  for (const item of items) {
    const name = routeNameOf(item.id);
    if (addedNames.has(name))
      continue;
    addedNames.add(name);
    router.addRoute("layout", buildRoute(item, shell));
  }
}
export async function syncMenuRoutes(router, menus, shell) {
  const items = [];
  walk(menus, items);
  const nextNames = new Set(items.map((i) => routeNameOf(i.id)));
  for (const name of [...addedNames]) {
    if (!nextNames.has(name)) {
      if (router.hasRoute(name))
        router.removeRoute(name);
      addedNames.delete(name);
    }
  }
  for (const item of items) {
    const name = routeNameOf(item.id);
    const childPath = item.router.replace(/^\//, "");
    if (addedNames.has(name) && router.hasRoute(name)) {
      const existing = router.getRoutes().find((r) => r.name === name);
      if (existing && existing.path.replace(/^\//, "") !== childPath) {
        router.removeRoute(name);
        addedNames.delete(name);
      } else if (existing?.meta) {
        existing.meta.title = item.name;
        existing.meta.keepAlive = item.keepAlive !== false;
        existing.meta.viewPath = item.viewPath;
        existing.meta.perms = item.perms;
        if (item.appKey)
          existing.meta.appKey = item.appKey;
        continue;
      }
    }
    if (!addedNames.has(name)) {
      addedNames.add(name);
      router.addRoute("layout", buildRoute(item, shell));
    }
  }
}
export function clearMenuRoutesFlag() {
  addedNames.clear();
}
export function removeAllMenuRoutes(router) {
  for (const name of [...addedNames]) {
    if (router.hasRoute(name))
      router.removeRoute(name);
  }
  addedNames.clear();
}
