(function bootstrapHyperTwistBrowserRuntime()
{
  const GlobalWindow = window;
  const ExistingBootState = GlobalWindow.HyperTwistBrowserBootState;
  const BootState = ExistingBootState && typeof ExistingBootState === 'object'
    ? ExistingBootState
    : {};

  if (!Array.isArray(BootState.pendingCommands))
  {
    BootState.pendingCommands = [];
  }
  if (!Array.isArray(BootState.pendingShellStates))
  {
    BootState.pendingShellStates = [];
  }

  BootState.bundleEntryUrl = new URL('./dist/browser-spatial-runtime.js', GlobalWindow.location.href).toString();
  BootState.fallbackEntryUrl = new URL('./src/browser-spatial-runtime-fallback.js', GlobalWindow.location.href).toString();
  BootState.runtimeMode = 'bootstrapping';
  BootState.bootstrapStartedAtUtc = new Date().toISOString();
  GlobalWindow.HyperTwistBrowserBootState = BootState;

  if (!GlobalWindow.HyperTwistBrowserRuntime || typeof GlobalWindow.HyperTwistBrowserRuntime !== 'object')
  {
    GlobalWindow.HyperTwistBrowserRuntime = {
      adapters: [],
      listAdapters()
      {
        return [];
      },
      loadAdapter()
      {
        return Promise.resolve({
          id: 'bootstrap-stub',
          note: 'Runtime bundle still bootstrapping.',
          status: 'deferred'
        });
      },
      receiveCommand(Payload)
      {
        BootState.pendingCommands.push(Payload);
      },
      setShellState(Payload)
      {
        BootState.pendingShellStates.push(Payload);
      },
      renderShell()
      {
      },
      sendState()
      {
      }
    };
  }

  let bFallbackRequested = false;

  function loadFallbackRuntime(Reason)
  {
    if (bFallbackRequested)
    {
      return;
    }

    bFallbackRequested = true;
    BootState.runtimeMode = 'fallback-js';
    BootState.fallbackReason = Reason;

    const FallbackScript = document.createElement('script');
    FallbackScript.src = BootState.fallbackEntryUrl;
    FallbackScript.defer = true;
    FallbackScript.dataset.hypertwistRuntime = 'fallback-js';
    document.head.appendChild(FallbackScript);
  }

  const BundledRuntimeScript = document.createElement('script');
  BundledRuntimeScript.type = 'module';
  BundledRuntimeScript.src = BootState.bundleEntryUrl;
  BundledRuntimeScript.dataset.hypertwistRuntime = 'bundled-module';
  BundledRuntimeScript.onload = function onBundledRuntimeLoaded()
  {
    GlobalWindow.setTimeout(function verifyBundledRuntime()
    {
      if (GlobalWindow.HyperTwistBrowserBootState?.runtimeMode === 'bundled-module')
      {
        return;
      }

      if (GlobalWindow.HyperTwistBrowserRuntime && GlobalWindow.HyperTwistBrowserRuntime.adapters?.length)
      {
        BootState.runtimeMode = 'bundled-module';
        return;
      }

      loadFallbackRuntime('bundle-loaded-without-runtime');
    }, 200);
  };
  BundledRuntimeScript.onerror = function onBundledRuntimeFailed()
  {
    loadFallbackRuntime('bundle-missing-or-failed');
  };
  document.head.appendChild(BundledRuntimeScript);

  GlobalWindow.setTimeout(function enforceRuntimeAvailability()
  {
    if (GlobalWindow.HyperTwistBrowserBootState?.runtimeMode === 'bundled-module')
    {
      return;
    }

    if (GlobalWindow.HyperTwistBrowserRuntime && GlobalWindow.HyperTwistBrowserRuntime.adapters?.length)
    {
      BootState.runtimeMode = 'bundled-module';
      return;
    }

    loadFallbackRuntime('bundle-timeout');
  }, 2000);
})();
