// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.

import { PageConfig, URLExt } from '@jupyterlab/coreutils';

// This must be after the public path is set.
// This cannot be extracted because the public path is dynamic.
require('./imports.css');

function loadScript(url) {
  return new Promise((resolve, reject) => {
    const newScript = document.createElement('script');
    newScript.onerror = reject;
    newScript.onload = resolve;
    newScript.async = true;
    document.head.appendChild(newScript);
    newScript.src = url;
  });
}

async function loadComponent(url, scope) {
  await loadScript(url);

  // From MIT-licensed https://github.com/module-federation/module-federation-examples/blob/af043acd6be1718ee195b2511adf6011fba4233c/advanced-api/dynamic-remotes/app1/src/App.js#L6-L12
  await __webpack_init_sharing__('default');
  const container = window._JUPYTERLAB[scope];
  // Initialize the container, it may provide shared modules and may need ours
  await container.init(__webpack_share_scopes__.default);
}

async function createModule(scope, module) {
  const factory = await window._JUPYTERLAB[scope].get(module);
  const Module = factory();
  return Module;
}


/**
 * The main entry point for the application.
 */
async function main() {
  var JupyterLab = require('@jupyterlab/application').JupyterLab;
  var disabled = [];
  var deferred = [];
  var ignorePlugins = [];
  var register = [];

  // This is all the data needed to load and activate plugins. This should be
  // gathered by the server and put onto the initial page template.
  const extension_data = JSON.parse(
    PageConfig.getOption('dynamic_extensions')
  );

  const dynamicPlugins = [];
  const dynamicMimePlugins = [];
  const dynamicStyles = [];

  // Get dynamic plugins
  // TODO: deconflict these with builtins?
  const componentLoadPromises = extension_data.map(async (data) => {
    await loadComponent(
      `${URLExt.join(PageConfig.getOption('fullLabextensionsUrl'), data.name, 'remoteEntry.js')}`,
      data.name
    )
    if (data.plugin) {
      dynamicPlugins.push(await createModule(data.name, data.plugin));
    }
    if (data.mimePlugin) {
      dynamicMimePlugins.push(await createModule(data.name, data.mimePlugin));
    }
    if (data.style) {
      dynamicStyles.push(await createModule(data.name, data.style));
    }
  });
  await Promise.all(componentLoadPromises);

  // Handle the registered mime extensions.
  var mimeExtensions = [];
  var extension;
  var extMod;
  var plugins = [];
  {{#each jupyterlab_mime_extensions}}
  try {
    extMod = require('{{@key}}/{{this}}');
    extension = extMod.default;

    // Handle CommonJS exports.
    if (!extMod.hasOwnProperty('__esModule')) {
      extension = extMod;
    }

    plugins = Array.isArray(extension) ? extension : [extension];
    plugins.forEach(function(plugin) {
      if (PageConfig.Extension.isDeferred(plugin.id)) {
        deferred.push(plugin.id);
        ignorePlugins.push(plugin.id);
      }
      if (PageConfig.Extension.isDisabled(plugin.id)) {
        disabled.push(plugin.id);
        return;
      }
      mimeExtensions.push(plugin);
    });
  } catch (e) {
    console.error(e);
  }
  {{/each}}

  // Add the dyanmic mime extensions.
  dynamicMimePlugins.forEach(plugin => { mimeExtensions.push(plugin); });

  // Handled the registered standard extensions.
  {{#each jupyterlab_extensions}}
  try {
    extMod = require('{{@key}}/{{this}}');
    extension = extMod.default;

    // Handle CommonJS exports.
    if (!extMod.hasOwnProperty('__esModule')) {
      extension = extMod;
    }

    plugins = Array.isArray(extension) ? extension : [extension];
    plugins.forEach(function(plugin) {
      if (PageConfig.Extension.isDeferred(plugin.id)) {
        deferred.push(plugin.id);
        ignorePlugins.push(plugin.id);
      }
      if (PageConfig.Extension.isDisabled(plugin.id)) {
        disabled.push(plugin.id);
        return;
      }
      register.push(plugin);
    });
  } catch (e) {
    console.error(e);
  }
  {{/each}}

  // Add the dynamic extensions.
  dynamicPlugins.forEach(plugin => { register.push(plugin) });

  var lab = new JupyterLab({
    mimeExtensions: mimeExtensions,
    disabled: {
      matches: disabled,
      patterns: PageConfig.Extension.disabled
        .map(function (val) { return val.raw; })
    },
    deferred: {
      matches: deferred,
      patterns: PageConfig.Extension.deferred
        .map(function (val) { return val.raw; })
    },
  });
  register.forEach(function(item) { lab.registerPluginModule(item); });
  lab.start({ ignorePlugins: ignorePlugins });
  lab.restored.then(() => {
    console.debug('Example started!');
  });
}

window.addEventListener('load', main);

@@ -1121,16 +1121,54 @@
 dule) %7B%0A
+  if (!module) %7B%0A    return null;%0A  %7D%0A
   const 
@@ -1222,16 +1222,16 @@
 odule);%0A
-
   const 
@@ -1805,36 +1805,8 @@
  %5B%5D;
-%0A  const dynamicStyles = %5B%5D;
 %0A%0A  
@@ -1922,22 +1922,16 @@
 ata.map(
-async 
 (data) =
@@ -1935,21 +1935,13 @@
 ) =%3E
- %7B
 %0A    
-await 
 load
@@ -2072,28 +2072,80 @@
 e%0A    )%0A    
-if (
+.then(() =%3E Promise.all(%5B%0A      createModule(data.name, 
 data.plugin)
@@ -2148,42 +2148,63 @@
 gin)
- %7B
+,
 %0A      
-dynamicPlugins.push(await
+createModule(data.name, data.mimePlugin),%0A     
  cre
@@ -2233,51 +2233,86 @@
 ata.
-plugin));
+style)
 %0A    
-%7D
+%5D))
 %0A    
-if (data.mimePlugin) %7B%0A
+.then((%5Bplugin, mimePlugin, _%5D) =%3E %7B%0A      if (plugin) %7B%0A  
     
@@ -2312,36 +2312,32 @@
 %0A        dynamic
-Mime
 Plugins.push(awa
@@ -2337,81 +2337,45 @@
 ush(
-await createModule(data.name, data.mimeP
+p
 lugin)
-)
 ;%0A    
+ 
+ 
 %7D%0A    
+ 
+ 
 if (
-data.style
+mimePlugin
 ) %7B%0A
@@ -2384,81 +2384,65 @@
     
+  
 dynamic
-Styles.push(await createModule(data.name, data.style)
+MimePlugins.push(mimePlugin
 );%0A
+  
     %7D%0A
+  
   %7D)
+%0A  )
 ;%0A  

Create modules in parallel