/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @polyfill
 *
 * @format
 */
"use strict";
/* eslint-disable no-bitwise */

global.__r = metroRequire;
global.__d = define;
global.__c = clear;
global.__registerSegment = registerSegment;
var modules = clear(); // Don't use a Symbol here, it would pull in an extra polyfill with all sorts of
// additional stuff (e.g. Array.from).

var EMPTY = {};
var _ref = {},
  hasOwnProperty = _ref.hasOwnProperty;

function clear() {
  modules = Object.create(null); // We return modules here so that we can assign an initial value to modules
  // when defining it. Otherwise, we would have to do "let modules = null",
  // which will force us to add "nullthrows" everywhere.

  return modules;
}

if (__DEV__) {
  var verboseNamesToModuleIds = Object.create(null);
  var initializingModuleIds = [];
}

function define(factory, moduleId, dependencyMap) {
  if (modules[moduleId] != null) {
    if (__DEV__) {
      // (We take `inverseDependencies` from `arguments` to avoid an unused
      // named parameter in `define` in production.
      var inverseDependencies = arguments[4]; // If the module has already been defined and the define method has been
      // called with inverseDependencies, we can hot reload it.

      if (inverseDependencies) {
        global.__accept(moduleId, factory, dependencyMap, inverseDependencies);
      }
    } // prevent repeated calls to `global.nativeRequire` to overwrite modules
    // that are already loaded

    return;
  }

  modules[moduleId] = {
    dependencyMap: dependencyMap,
    factory: factory,
    hasError: false,
    importedAll: EMPTY,
    importedDefault: EMPTY,
    isInitialized: false,
    publicModule: {
      exports: {}
    }
  };

  if (__DEV__) {
    // HMR
    modules[moduleId].hot = createHotReloadingObject(); // DEBUGGABLE MODULES NAMES
    // we take `verboseName` from `arguments` to avoid an unused named parameter
    // in `define` in production.

    var verboseName = arguments[3];

    if (verboseName) {
      modules[moduleId].verboseName = verboseName;
      verboseNamesToModuleIds[verboseName] = moduleId;
    }
  }
}

function metroRequire(moduleId) {
  if (__DEV__ && typeof moduleId === "string") {
    var verboseName = moduleId;
    moduleId = verboseNamesToModuleIds[verboseName];

    if (moduleId == null) {
      throw new Error('Unknown named module: "'.concat(verboseName, '"'));
    } else {
      console.warn(
        'Requiring module "'.concat(
          verboseName,
          '" by name is only supported for '
        ) + "debugging purposes and will BREAK IN PRODUCTION!"
      );
    }
  } //$FlowFixMe: at this point we know that moduleId is a number

  var moduleIdReallyIsNumber = moduleId;

  if (__DEV__) {
    var initializingIndex = initializingModuleIds.indexOf(
      moduleIdReallyIsNumber
    );

    if (initializingIndex !== -1) {
      var cycle = initializingModuleIds
        .slice(initializingIndex)
        .map(function(id) {
          return modules[id].verboseName;
        }); // We want to show A -> B -> A:

      cycle.push(cycle[0]);
      console.warn(
        "Require cycle: ".concat(cycle.join(" -> "), "\n\n") +
          "Require cycles are allowed, but can result in uninitialized values. " +
          "Consider refactoring to remove the need for a cycle."
      );
    }
  }

  var module = modules[moduleIdReallyIsNumber];
  return module && module.isInitialized
    ? module.publicModule.exports
    : guardedLoadModule(moduleIdReallyIsNumber, module);
}

function metroImportDefault(moduleId) {
  if (__DEV__ && typeof moduleId === "string") {
    var verboseName = moduleId;
    moduleId = verboseNamesToModuleIds[verboseName];
  } //$FlowFixMe: at this point we know that moduleId is a number

  var moduleIdReallyIsNumber = moduleId;

  if (
    modules[moduleIdReallyIsNumber] &&
    modules[moduleIdReallyIsNumber].importedDefault !== EMPTY
  ) {
    return modules[moduleIdReallyIsNumber].importedDefault;
  }

  var exports = metroRequire(moduleIdReallyIsNumber);
  var importedDefault =
    exports && exports.__esModule ? exports.default : exports;
  return (modules[moduleIdReallyIsNumber].importedDefault = importedDefault);
}

metroRequire.importDefault = metroImportDefault;

function metroImportAll(moduleId) {
  if (__DEV__ && typeof moduleId === "string") {
    var verboseName = moduleId;
    moduleId = verboseNamesToModuleIds[verboseName];
  } //$FlowFixMe: at this point we know that moduleId is a number

  var moduleIdReallyIsNumber = moduleId;

  if (
    modules[moduleIdReallyIsNumber] &&
    modules[moduleIdReallyIsNumber].importedAll !== EMPTY
  ) {
    return modules[moduleIdReallyIsNumber].importedAll;
  }

  var exports = metroRequire(moduleIdReallyIsNumber);
  var importedAll;

  if (exports && exports.__esModule) {
    importedAll = exports;
  } else {
    importedAll = {}; // Refrain from using Object.assign, it has to work in ES3 environments.

    if (exports) {
      for (var _key in exports) {
        if (hasOwnProperty.call(exports, _key)) {
          importedAll[_key] = exports[_key];
        }
      }
    }

    importedAll.default = exports;
  }

  return (modules[moduleIdReallyIsNumber].importedAll = importedAll);
}

metroRequire.importAll = metroImportAll;
var inGuard = false;

function guardedLoadModule(moduleId, module) {
  if (!inGuard && global.ErrorUtils) {
    inGuard = true;
    var returnValue;

    try {
      returnValue = loadModuleImplementation(moduleId, module);
    } catch (e) {
      global.ErrorUtils.reportFatalError(e);
    }

    inGuard = false;
    return returnValue;
  } else {
    return loadModuleImplementation(moduleId, module);
  }
}

var ID_MASK_SHIFT = 16;
var LOCAL_ID_MASK = ~0 >>> ID_MASK_SHIFT;

function unpackModuleId(moduleId) {
  var segmentId = moduleId >>> ID_MASK_SHIFT;
  var localId = moduleId & LOCAL_ID_MASK;
  return {
    segmentId: segmentId,
    localId: localId
  };
}

metroRequire.unpackModuleId = unpackModuleId;

function packModuleId(value) {
  return (value.segmentId << ID_MASK_SHIFT) + value.localId;
}

metroRequire.packModuleId = packModuleId;
var hooks = [];

function registerHook(cb) {
  var hook = {
    cb: cb
  };
  hooks.push(hook);
  return {
    release: function release() {
      for (var i = 0; i < hooks.length; ++i) {
        if (hooks[i] === hook) {
          hooks.splice(i, 1);
          break;
        }
      }
    }
  };
}

metroRequire.registerHook = registerHook;
var moduleDefinersBySegmentID = [];

function registerSegment(segmentID, moduleDefiner) {
  moduleDefinersBySegmentID[segmentID] = moduleDefiner;
}

function loadModuleImplementation(moduleId, module) {
  if (!module && moduleDefinersBySegmentID.length > 0) {
    var _unpackModuleId = unpackModuleId(moduleId),
      segmentId = _unpackModuleId.segmentId,
      localId = _unpackModuleId.localId;

    var definer = moduleDefinersBySegmentID[segmentId];

    if (definer != null) {
      definer(localId);
      module = modules[moduleId];
    }
  }

  var nativeRequire = global.nativeRequire;

  if (!module && nativeRequire) {
    var _unpackModuleId2 = unpackModuleId(moduleId),
      _segmentId = _unpackModuleId2.segmentId,
      _localId = _unpackModuleId2.localId;

    nativeRequire(_localId, _segmentId);
    module = modules[moduleId];
  }

  if (!module) {
    throw unknownModuleError(moduleId);
  }

  if (module.hasError) {
    throw moduleThrewError(moduleId, module.error);
  } // `metroRequire` calls into the require polyfill itself are not analyzed and
  // replaced so that they use numeric module IDs.
  // The systrace module will expose itself on the metroRequire function so that
  // it can be used here.
  // TODO(davidaurelio) Scan polyfills for dependencies, too (t9759686)

  if (__DEV__) {
    var Systrace = metroRequire.Systrace;
  } // We must optimistically mark module as initialized before running the
  // factory to keep any require cycles inside the factory from causing an
  // infinite require loop.

  module.isInitialized = true;
  var _module = module,
    factory = _module.factory,
    dependencyMap = _module.dependencyMap;

  if (__DEV__) {
    initializingModuleIds.push(moduleId);
  }

  try {
    if (__DEV__) {
      // $FlowFixMe: we know that __DEV__ is const and `Systrace` exists
      Systrace.beginEvent("JS_require_" + (module.verboseName || moduleId));
    }

    var _moduleObject = module.publicModule;

    if (__DEV__) {
      if (module.hot) {
        _moduleObject.hot = module.hot;
      }
    }

    _moduleObject.id = moduleId;

    if (hooks.length > 0) {
      for (var i = 0; i < hooks.length; ++i) {
        hooks[i].cb(moduleId, _moduleObject);
      }
    } // keep args in sync with with defineModuleCode in
    // metro/src/Resolver/index.js
    // and metro/src/ModuleGraph/worker.js

    factory(
      global,
      metroRequire,
      metroImportDefault,
      metroImportAll,
      _moduleObject,
      _moduleObject.exports,
      dependencyMap
    ); // avoid removing factory in DEV mode as it breaks HMR

    if (!__DEV__) {
      // $FlowFixMe: This is only sound because we never access `factory` again
      module.factory = undefined;
      module.dependencyMap = undefined;
    }

    if (__DEV__) {
      // $FlowFixMe: we know that __DEV__ is const and `Systrace` exists
      Systrace.endEvent();
    }

    return _moduleObject.exports;
  } catch (e) {
    module.hasError = true;
    module.error = e;
    module.isInitialized = false;
    module.publicModule.exports = undefined;
    throw e;
  } finally {
    if (__DEV__) {
      if (initializingModuleIds.pop() !== moduleId) {
        throw new Error(
          "initializingModuleIds is corrupt; something is terribly wrong"
        );
      }
    }
  }
}

function unknownModuleError(id) {
  var message = 'Requiring unknown module "' + id + '".';

  if (__DEV__) {
    message +=
      "If you are sure the module is there, try restarting Metro Bundler. " +
      "You may also want to run `yarn`, or `npm install` (depending on your environment).";
  }

  return Error(message);
}

function moduleThrewError(id, error) {
  var displayName = (__DEV__ && modules[id] && modules[id].verboseName) || id;
  return Error(
    'Requiring module "' + displayName + '", which threw an exception: ' + error
  );
}

if (__DEV__) {
  metroRequire.Systrace = {
    beginEvent: function beginEvent() {},
    endEvent: function endEvent() {}
  };

  metroRequire.getModules = function() {
    return modules;
  }; // HOT MODULE RELOADING

  var createHotReloadingObject = function createHotReloadingObject() {
    var hot = {
      acceptCallback: null,
      accept: function accept(callback) {
        hot.acceptCallback = callback;
      },
      disposeCallback: null,
      dispose: function dispose(callback) {
        hot.disposeCallback = callback;
      }
    };
    return hot;
  };

  var metroAcceptAll = function metroAcceptAll(
    dependentModules,
    inverseDependencies,
    patchedModules
  ) {
    if (!dependentModules || dependentModules.length === 0) {
      return true;
    }

    var notAccepted = dependentModules.filter(function(module) {
      return !metroAccept(
        module,
        /*factory*/
        undefined,
        /*dependencyMap*/
        undefined,
        inverseDependencies,
        patchedModules
      );
    });
    var parents = [];

    for (var i = 0; i < notAccepted.length; i++) {
      // if the module has no parents then the change cannot be hot loaded
      if (inverseDependencies[notAccepted[i]].length === 0) {
        return false;
      }

      parents.push.apply(parents, inverseDependencies[notAccepted[i]]);
    }

    return parents.length == 0;
  };

  var metroAccept = function metroAccept(
    id,
    factory,
    dependencyMap,
    inverseDependencies
  ) {
    var patchedModules =
      arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};

    if (id in patchedModules) {
      // Do not patch the same module more that once during an update.
      return true;
    }

    patchedModules[id] = true;
    var mod = modules[id];

    if (!mod && factory) {
      // New modules are going to be handled by the define() method.
      return true;
    }

    var hot = mod.hot;

    if (!hot) {
      console.warn(
        "Cannot accept module because Hot Module Replacement " +
          "API was not installed."
      );
      return false;
    }

    if (hot.disposeCallback) {
      try {
        hot.disposeCallback();
      } catch (error) {
        console.error(
          "Error while calling dispose handler for module ".concat(id, ": "),
          error
        );
      }
    } // replace and initialize factory

    if (factory) {
      mod.factory = factory;
    }

    if (dependencyMap) {
      mod.dependencyMap = dependencyMap;
    }

    mod.hasError = false;
    mod.isInitialized = false;
    metroRequire(id);

    if (hot.acceptCallback) {
      try {
        hot.acceptCallback();
        return true;
      } catch (error) {
        console.error(
          "Error while calling accept handler for module ".concat(id, ": "),
          error
        );
      }
    } // need to have inverseDependencies to bubble up accept

    if (!inverseDependencies) {
      throw new Error("Undefined `inverseDependencies`");
    } // accept parent modules recursively up until all siblings are accepted

    return metroAcceptAll(
      inverseDependencies[id],
      inverseDependencies,
      patchedModules
    );
  };

  global.__accept = metroAccept;
}