text: import { __read, __spread, __values } from "tslib";
  import { isClassProvider, isFactoryProvider, isNormalToken, isTokenProvider, isValueProvider } from "./providers";
  import { isProvider } from "./providers/provider";
  import { isConstructorToken, isTokenDescriptor } from "./providers/injection-token";
  import Registry from "./registry";
  import Lifecycle from "./types/lifecycle";
  import ResolutionContext from "./resolution-context";
  import { formatErrorCtor } from "./error-helpers";
  import { DelayedConstructor } from "./lazy-helpers";
  export var typeInfo = new Map();
  var InternalDependencyContainer = (function () {
      function InternalDependencyContainer(parent) {
          this.parent = parent;
          this._registry = new Registry();
      }
      InternalDependencyContainer.prototype.register = function (token, providerOrConstructor, options) {
          if (options === void 0) { options = { lifecycle: Lifecycle.Transient }; }
          var provider;
          if (!isProvider(providerOrConstructor)) {
              provider = { useClass: providerOrConstructor };
          }
          else {
              provider = providerOrConstructor;
          }
          if (options.lifecycle === Lifecycle.Singleton ||
              options.lifecycle == Lifecycle.ContainerScoped ||
              options.lifecycle == Lifecycle.ResolutionScoped) {
              if (isValueProvider(provider) || isFactoryProvider(provider)) {
                  throw new Error("Cannot use lifecycle \"" + Lifecycle[options.lifecycle] + "\" with ValueProviders or FactoryProviders");
              }
          }
          this._registry.set(token, { provider: provider, options: options });
          return this;
      };
      InternalDependencyContainer.prototype.registerType = function (from, to) {
          if (isNormalToken(to)) {
              return this.register(from, {
                  useToken: to
              });
          }
          return this.register(from, {
              useClass: to
          });
      };
      InternalDependencyContainer.prototype.registerInstance = function (token, instance) {
          return this.register(token, {
              useValue: instance
          });
      };
      InternalDependencyContainer.prototype.registerSingleton = function (from, to) {
          if (isNormalToken(from)) {
              if (isNormalToken(to)) {
                  return this.register(from, {
                      useToken: to
                  }, { lifecycle: Lifecycle.Singleton });
              }
              else if (to) {
                  return this.register(from, {
                      useClass: to
                  }, { lifecycle: Lifecycle.Singleton });
              }
              throw new Error('Cannot register a type name as a singleton without a "to" token');
          }
          var useClass = from;
          if (to && !isNormalToken(to)) {
              useClass = to;
          }
          return this.register(from, {
              useClass: useClass
          }, { lifecycle: Lifecycle.Singleton });
      };
      InternalDependencyContainer.prototype.resolve = function (token, context) {
          if (context === void 0) { context = new ResolutionContext(); }
          var registration = this.getRegistration(token);
          if (!registration && isNormalToken(token)) {
              throw new Error("Attempted to resolve unregistered dependency token: \"" + token.toString() + "\"");
          }
          if (registration) {
              return this.resolveRegistration(registration, context);
          }
          if (isConstructorToken(token)) {
              return this.construct(token, context);
          }
          throw new Error("Attempted to construct an undefined constructor. Could mean a circular dependency problem. Try using `delay` function.");
      };
      InternalDependencyContainer.prototype.resolveRegistration = function (registration, context) {
          if (registration.options.lifecycle === Lifecycle.ResolutionScoped &&
              context.scopedResolutions.has(registration)) {
              return context.scopedResolutions.get(registration);
          }
          var isSingleton = registration.options.lifecycle === Lifecycle.Singleton;
          var isContainerScoped = registration.options.lifecycle === Lifecycle.ContainerScoped;
          var returnInstance = isSingleton || isContainerScoped;
          var resolved;
          if (isValueProvider(registration.provider)) {
              resolved = registration.provider.useValue;
          }
          else if (isTokenProvider(registration.provider)) {
              resolved = returnInstance
                  ? registration.instance ||
                      (registration.instance = this.resolve(registration.provider.useToken, context))
                  : this.resolve(registration.provider.useToken, context);
          }
          else if (isClassProvider(registration.provider)) {
              resolved = returnInstance
                  ? registration.instance ||
                      (registration.instance = this.construct(registration.provider.useClass, context))
                  : this.construct(registration.provider.useClass, context);
          }
          else if (isFactoryProvider(registration.provider)) {
              resolved = registration.provider.useFactory(this);
          }
          else {
              resolved = this.construct(registration.provider, context);
          }
          if (registration.options.lifecycle === Lifecycle.ResolutionScoped) {
              context.scopedResolutions.set(registration, resolved);
          }
          return resolved;
      };
      InternalDependencyContainer.prototype.resolveAll = function (token, context) {
          var _this = this;
          if (context === void 0) { context = new ResolutionContext(); }
          var registrations = this.getAllRegistrations(token);
          if (!registrations && isNormalToken(token)) {
              throw new Error("Attempted to resolve unregistered dependency token: \"" + token.toString() + "\"");
          }
          if (registrations) {
              return registrations.map(function (item) {
                  return _this.resolveRegistration(item, context);
              });
          }
          return [this.construct(token, context)];
      };
      InternalDependencyContainer.prototype.isRegistered = function (token, recursive) {
          if (recursive === void 0) { recursive = false; }
          return (this._registry.has(token) ||
              (recursive &&
                  (this.parent || false) &&
                  this.parent.isRegistered(token, true)));
      };
      InternalDependencyContainer.prototype.reset = function () {
          this._registry.clear();
      };
      InternalDependencyContainer.prototype.clearInstances = function () {
          var e_1, _a;
          try {
              for (var _b = __values(this._registry.entries()), _c = _b.next(); !_c.done; _c = _b.next()) {
                  var _d = __read(_c.value, 2), token = _d[0], registrations = _d[1];
                  this._registry.setAll(token, registrations
                      .filter(function (registration) { return !isValueProvider(registration.provider); })
                      .map(function (registration) {
                      registration.instance = undefined;
                      return registration;
                  }));
              }
          }
          catch (e_1_1) { e_1 = { error: e_1_1 }; }
          finally {
              try {
                  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
              }
              finally { if (e_1) throw e_1.error; }
          }
      };
      InternalDependencyContainer.prototype.createChildContainer = function () {
          var e_2, _a;
          var childContainer = new InternalDependencyContainer(this);
          try {
              for (var _b = __values(this._registry.entries()), _c = _b.next(); !_c.done; _c = _b.next()) {
                  var _d = __read(_c.value, 2), token = _d[0], registrations = _d[1];
                  if (registrations.some(function (_a) {
                      var options = _a.options;
                      return options.lifecycle === Lifecycle.ContainerScoped;
                  })) {
                      childContainer._registry.setAll(token, registrations.map(function (registration) {
                          if (registration.options.lifecycle === Lifecycle.ContainerScoped) {
                              return {
                                  provider: registration.provider,
                                  options: registration.options
                              };
                          }
                          return registration;
                      }));
                  }
              }
          }
          catch (e_2_1) { e_2 = { error: e_2_1 }; }
          finally {
              try {
                  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
              }
              finally { if (e_2) throw e_2.error; }
          }
          return childContainer;
      };
      InternalDependencyContainer.prototype.getRegistration = function (token) {
          if (this.isRegistered(token)) {
              return this._registry.get(token);
          }
          if (this.parent) {
              return this.parent.getRegistration(token);
          }
          return null;
      };
      InternalDependencyContainer.prototype.getAllRegistrations = function (token) {
          if (this.isRegistered(token)) {
              return this._registry.getAll(token);
          }
          if (this.parent) {
              return this.parent.getAllRegistrations(token);
          }
          return null;
      };
      InternalDependencyContainer.prototype.construct = function (ctor, context) {
          var _this = this;
          if (ctor instanceof DelayedConstructor) {
              return ctor.createProxy(function (target) {
                  return _this.resolve(target, context);
              });
          }
          if (ctor.length === 0) {
              return new ctor();
          }
          var paramInfo = typeInfo.get(ctor);
          if (!paramInfo || paramInfo.length === 0) {
              throw new Error("TypeInfo not known for \"" + ctor.name + "\"");
          }
          var params = paramInfo.map(this.resolveParams(context, ctor));
          return new (ctor.bind.apply(ctor, __spread([void 0], params)))();
      };
      InternalDependencyContainer.prototype.resolveParams = function (context, ctor) {
          var _this = this;
          return function (param, idx) {
              try {
                  if (isTokenDescriptor(param)) {
                      return param.multiple
                          ? _this.resolveAll(param.token)
                          : _this.resolve(param.token, context);
                  }
                  return _this.resolve(param, context);
              }
              catch (e) {
                  throw new Error(formatErrorCtor(ctor, idx, e));
              }
          };
      };
      return InternalDependencyContainer;
  }());
  export var instance = new InternalDependencyContainer();
  export default instance;
  