import * as ReactDOM from 'react-dom'

// Let compiler not to search module usage
const fullClone = {
  ...ReactDOM,
}

const { version, render: reactRender, unmountComponentAtNode } = fullClone;

/**
 * @type {typeof CreateRoot}
 */
let createRoot;
try {
  const mainVersion = Number((version || '').split('.')[0]);
  if (mainVersion >= 18) {
    ({ createRoot } = fullClone);
  }
} catch (e) {
  // Do nothing;
}

/**
 * 
 * @param {Boolean} skip 是否跳过
 */
function toggleWarning(skip) {
  const { __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED } = fullClone;

  if (
    __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED &&
    typeof __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED === 'object'
  ) {
    __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.usingClientEntryPoint =
      skip;
  }
}

const MARK = '__rc_react_root__';

/**
 * 新的渲染模式
 * @param {React.ReactElement} node React节点
 * @param {Element | DocumentFragment} container 
 */
function modernRender(node, container) {
  toggleWarning(true);
  const root = container[MARK] || createRoot(container);
  toggleWarning(false);

  root.render(node);

  container[MARK] = root;
}

/**
 * 旧的渲染模式
 * @param {React.ReactElement} node React节点
 * @param {Element | DocumentFragment} container 
 */
function legacyRender(node, container) {
  reactRender(node, container);
}

/**
 * 渲染
 * @param {React.ReactElement} node React节点
 * @param {Element | DocumentFragment} container 
 * @returns 
 */
export function render(node, container) {
  if (createRoot) {
    modernRender(node, container);
    return;
  }

  legacyRender(node, container);
}

// ========================= Unmount ==========================
/**
 * 新的卸载方式
 * @param {Element | DocumentFragment} container 
 * @returns 
 */
async function modernUnmount(container) {
  // Delay to unmount to avoid React 18 sync warning
  return Promise.resolve().then(() => {
    container[MARK]?.unmount();

    delete container[MARK];
  });
}

/**
 * 旧的卸载方式
 * @param {Element | DocumentFragment} container 
 */
function legacyUnmount(container) {
  unmountComponentAtNode(container);
}

/**
 * 卸载
 * @param {Element | DocumentFragment} container 
 * @returns 
 */
export async function unmount(container) {
  if (createRoot !== undefined) {
    // Delay to unmount to avoid React 18 sync warning
    return modernUnmount(container);
  }

  legacyUnmount(container);
}
