"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var app_factory_exports = {};
__export(app_factory_exports, {
  loadApp: () => loadApp,
  mountApp: () => mountApp,
  unloadApp: () => unloadApp,
  unmountApp: () => unmountApp
});
module.exports = __toCommonJS(app_factory_exports);
var import_web_storage = require("../../../utils/web-storage.js");
var import_host = require("../../../utils/micro-frontend/host.js");
var import_micro_frontend = require("../../../utils/micro-frontend/index.js");
var import_log_records = require("../../../utils/log-records.js");
var import_const = require("../const.js");
var import_window = require("../../../utils/window.js");
var import_style = require("../resources/style.js");
var import_script = require("../resources/script.js");
var import_manifest = require("../resources/manifest.js");
const cssType = /\.css$/;
const isCss = (fileName) => cssType.test(fileName);
const activeApps = {};
const getPathName = (url) => url ? new URL(url).pathname : "";
const getAppNotFoundError = (id, uuid) => `Application ${id} with instance id ${uuid} is not found. Most probably the appId property of app.config.json is not set to ${id}`;
const getMicroAppGuestFromWindow = ({
  id,
  uuid
}) => {
  let microAppGuest = null;
  const guests = window.emui?.[id];
  if (Array.isArray(guests)) {
    microAppGuest = guests.find((guest) => guest.uuid === uuid) ?? null;
  } else {
    microAppGuest = guests;
  }
  return microAppGuest;
};
const initApplication = async ({
  id,
  uuid,
  name,
  hostUrl,
  history,
  theme,
  manifestPath,
  homeRoute
}) => {
  const app = getMicroAppGuestFromWindow({
    id,
    uuid
  });
  if (!app) throw new Error(getAppNotFoundError(id, uuid));
  const { init } = app;
  if (!init || typeof init !== "function")
    throw new Error(
      `Application ${name} with id ${id} doesn't expose init method.`
    );
  const prevState = await import_web_storage.persistentStorage.get(
    `state-${id}-${uuid}`
  );
  return init({
    host: import_host.CMicroAppHost.getInstance(),
    hostUrl,
    manifestPath,
    homeRoute: homeRoute ?? getPathName(hostUrl),
    prevState,
    history,
    theme,
    hostBreakpoint: (0, import_window.getCurrentBreakpoint)(),
    hostViewportSize: (0, import_window.getViewportSize)()
  });
};
const mountApp = async ({ id, uuid, name }) => {
  const app = getMicroAppGuestFromWindow({
    id,
    uuid
  });
  if (!app) throw new Error(getAppNotFoundError(id, uuid));
  const { mount } = app;
  if (!mount || typeof mount !== "function")
    throw new Error(
      `Application ${name} with id ${id} doesn't expose mount method.`
    );
  return mount({
    containerId: `${import_const.APP_CONTAINER_ID_PREFIX}${id}`,
    hostBreakpoint: (0, import_window.getCurrentBreakpoint)(),
    hostViewportSize: (0, import_window.getViewportSize)()
  });
};
const unmountApp = async ({ id, uuid, name }) => {
  const app = getMicroAppGuestFromWindow({
    id,
    uuid
  });
  if (!app) return null;
  const { unmount } = app;
  if (!unmount) return null;
  if (typeof unmount !== "function")
    throw new Error(
      `unmount failed for application ${name} with id ${id}. unmount is not a valid function`
    );
  const currentState = await unmount({
    containerId: `${import_const.APP_CONTAINER_ID_PREFIX}${id}`
  });
  if (currentState) {
    await import_web_storage.persistentStorage.set(`state-${id}-${uuid}`, currentState);
  }
  return Promise.resolve();
};
const addAppToActiveAppList = (id, uuid, elementIds) => {
  const app = getMicroAppGuestFromWindow({
    id,
    uuid
  });
  if (!app) throw new Error(getAppNotFoundError(id, uuid));
  const { getRef } = app;
  activeApps[`${id}-${uuid}`] = { elementIds };
  const host = import_host.CMicroAppHost.getInstance();
  if (host) host.activeGuests[`${id}-${uuid}`] = getRef && getRef() || {};
  return Promise.resolve();
};
const waitAndInitApplication = (appConfig, requests) => (
  // wait for all assets to get downloaded
  Promise.all(requests).then(addAppToActiveAppList.bind(null, appConfig.id, appConfig.uuid)).then(initApplication.bind(null, appConfig)).catch((err) => {
    const logRecord = import_log_records.logRecords.APP_INIT_FAILED(
      appConfig.id,
      appConfig.uuid,
      err.message
    );
    (0, import_micro_frontend.getLogger)().error({ ...logRecord, exception: err });
    throw new Error(logRecord.message);
  })
);
const removeAssetsFromDOM = (id, uuid, documentEle = document) => {
  const host = import_host.CMicroAppHost.getInstance();
  if (host) delete host.activeGuests[`${id}-${uuid}`];
  const { elementIds } = activeApps[`${id}-${uuid}`] || {};
  if (elementIds) {
    elementIds.forEach((elementId) => {
      const ele = documentEle.getElementById(elementId);
      if (ele) ele.remove();
    });
    delete activeApps[`${id}-${uuid}`];
  }
};
const addAppToGlobalVariable = ({
  id,
  uuid,
  documentEle
}) => {
  const newAppInstance = {
    uuid,
    init: null,
    mount: null,
    unmount: null,
    getRef: null,
    navigate: null
  };
  const app = getMicroAppGuestFromWindow({ id, uuid });
  if (app) {
    if (!uuid) {
      throw new Error(
        `Application ${id} is already loaded. uuid is required to load multiple instances of the same app`
      );
    }
    if (Array.isArray(window.emui[id])) {
      window.emui[id].push(newAppInstance);
    } else if (typeof app.init === "undefined") {
      window.emui[id] = { ...window.emui[id], ...newAppInstance };
    } else {
      window.emui[id] = [window.emui[id], newAppInstance];
    }
  } else {
    window.emui[id] = newAppInstance;
  }
  if (documentEle.defaultView) {
    documentEle.defaultView.emui = documentEle.defaultView.emui ?? {};
    documentEle.defaultView.emui.uuid = uuid;
  }
};
const removeAppFromGlobalVariable = (id, uuid) => {
  if (Array.isArray(window.emui[id])) {
    const index = window.emui[id].findIndex(
      (app) => app.uuid === uuid
    );
    if (index > -1) window.emui[id].splice(index, 1);
  } else {
    delete window.emui[id];
  }
};
const loadApp = async (appConfig) => {
  const { id, uuid, documentEle, isJsModule } = appConfig;
  addAppToGlobalVariable({ id, uuid, documentEle });
  try {
    (0, import_micro_frontend.getLogger)().info(import_log_records.logRecords.APP_LOADING(id, uuid));
    let assets = appConfig.files;
    const manifest = await (0, import_manifest.getAppManifest)(appConfig);
    assets = (0, import_manifest.getFullFileNameofAssetsFromManifest)(manifest, appConfig.files);
    let counter = 0;
    const requests = assets.map((fileName) => {
      counter += 1;
      return !isCss(fileName) ? (0, import_script.addScriptToDOM)(appConfig, fileName, counter, isJsModule) : (0, import_style.addStylesToDOM)(appConfig, fileName, counter);
    });
    await waitAndInitApplication(appConfig, requests);
    (0, import_micro_frontend.getLogger)().info(import_log_records.logRecords.APP_LOADING_COMPLETE(id, uuid));
  } catch (err) {
    removeAppFromGlobalVariable(id, uuid);
    throw err;
  }
};
const unloadApp = ({
  id,
  uuid,
  hostUrl,
  documentEle
}) => {
  if (!hostUrl) throw new Error("Unable to unload app. hostUrl is required");
  (0, import_micro_frontend.getLogger)().info(import_log_records.logRecords.APP_UNLOADING(id, uuid));
  const app = getMicroAppGuestFromWindow({ id, uuid });
  if (!app) return;
  removeAssetsFromDOM(id, uuid, documentEle);
  (0, import_script.removeDynamicImportedScripts)(hostUrl, documentEle);
  (0, import_script.removePrefetchLinks)(hostUrl, documentEle);
  (0, import_style.removeDynamicImportedStyles)(hostUrl, documentEle);
  removeAppFromGlobalVariable(id, uuid);
  (0, import_micro_frontend.getLogger)().info(import_log_records.logRecords.APP_UNLOADING_COMPLETE(id, uuid));
};
