/**
 * Copyright 2020 Google Inc. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// If the loader is already loaded, just stop.
if (!self.<%- amdFunctionName %>) {
  const singleRequire = async name => {
    if (name === 'require') return require;
    let url;
    if (name.startsWith(location.origin)) {
      url = name.slice(location.origin.length);
    } else {
      url = name.slice(1) + '.js';
    }
    if (!url.startsWith('/c/')) {
      url = '/c' + url;
    }
    name = './static' + url;
    if (registry[name]) return registry[name];

    if (!registry[name]) {
      <% if (useEval) { %>
        const text = await fetch(url).then(resp => resp.text());
        eval(text);
      <% } else { %>
        if ("document" in self) {
          await new Promise(resolve => {
            const script = document.createElement("script");
            script.src = url;
            document.head.appendChild(script);
            script.onload = resolve;
          });
        } else {
          importScripts(url);
        }
      <% } %>
    }
    if (!registry[name]) {
      throw new Error(`Module ${name} didn’t register its module`);
    }
    return registry[name];
  };

  const require = (names, resolve) => {
    Promise.all(names.map(singleRequire))
      .then(modules => resolve(modules.length === 1 ? modules[0] : modules));
  };

  const registry = {
    require: Promise.resolve(require)
  };

  self.<%- amdFunctionName %> = (moduleName, depsNames, factory) => {
    if (registry[moduleName]) {
      // Module is already loading or loaded.
      return;
    }
    registry[moduleName] = Promise.resolve().then(() => {
      let exports = {};
      const module = {
        uri: location.origin + moduleName.slice(1)
      };
      return Promise.all(
        depsNames.map(depName => {
          switch(depName) {
            case "exports":
              return exports;
            case "module":
              return module;
            default:
              return singleRequire(depName);
          }
        })
      ).then(deps => {
        const facValue = factory(...deps);
        if (!exports.default) {
          exports.default = facValue;
        }
        return exports;
      });
    });
  };
}
