import { useRef, useLayoutEffect, useCallback } from "react";
import { merge } from "lodash";
import { useDispatch } from "react-redux";
import { waitMessage } from "../../data/wait-message/actions.js";
import {
  loadApp,
  unloadApp,
  mountApp,
  unmountApp
} from "./app-factory/index.js";
import {
  getLogger,
  getMicroFrontEndAppConfig
} from "../../utils/micro-frontend/index.js";
import { logRecords } from "../../utils/log-records.js";
const useAppWillRender = ({
  id,
  uuid,
  documentEle,
  history,
  theme,
  homeRoute,
  onUnloadComplete
}) => {
  const dispatch = useDispatch ? useDispatch() : null;
  const ref = useRef(Promise.resolve());
  const getConfig = useCallback(
    () => getMicroFrontEndAppConfig({
      id
    }),
    [id]
  );
  const unload = useCallback(
    async (appParams, loadFailed = false) => {
      await unmountApp(appParams);
      unloadApp(appParams);
      if (!loadFailed && onUnloadComplete) onUnloadComplete();
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    []
  );
  const load = useCallback(
    async (appParams) => {
      if (dispatch) dispatch(waitMessage.open());
      try {
        if (ref.current) await ref.current;
        await loadApp(appParams);
        await mountApp(appParams);
      } catch (ex) {
        getLogger().error({
          ...logRecords.APP_CONFIG_LOAD_FAILED,
          exception: ex
        });
        await unload(appParams, true);
        throw ex;
      }
      if (dispatch) dispatch(waitMessage.close());
    },
    [dispatch, unload]
  );
  useLayoutEffect(() => {
    if (!documentEle) return () => {
    };
    const appConfig = merge(getConfig(), {
      documentEle,
      history,
      theme,
      homeRoute
    });
    const appParams = { ...appConfig, uuid };
    load(appParams);
    return () => {
      ref.current = unload(appParams);
    };
  }, [documentEle, getConfig, history, theme, homeRoute, load, unload, uuid]);
};
export {
  useAppWillRender
};
