// Copyright 2006 The Closure Library Authors. 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.

/**
 * @fileoverview Bootstrap for the Google JS Library (Closure).
 *
 * In uncompiled mode base.js will attempt to load Closure's deps file, unless
 * the global <code>CLOSURE_NO_DEPS</code> is set to true.  This allows projects
 * to include their own deps file(s) from different locations.
 *
 * Avoid including base.js more than once. This is strictly discouraged and not
 * supported. goog.require(...) won't work properly in that case.
 *
 * @provideGoog
 */


/**
 * Base namespace for the Closure library.  Checks to see goog is already
 * defined in the current scope before assigning to prevent clobbering if
 * base.js is loaded more than once.
 *
 * @const
 */
 var goog = goog || {};

 /**
  * Reference to the global object.
  * https://www.ecma-international.org/ecma-262/9.0/index.html#sec-global-object
  *
  * More info on this implementation here:
  * https://docs.google.com/document/d/1NAeW4Wk7I7FV0Y2tcUFvQdGMc89k2vdgSXInw8_nvCI/edit
  *
  * @const
  * @suppress {undefinedVars} self won't be referenced unless `this` is falsy.
  * @type {!Global}
  */
 goog.global =
     // Check `this` first for backwards compatibility.
     // Valid unless running as an ES module or in a function wrapper called
     //   without setting `this` properly.
     // Note that base.js can't usefully be imported as an ES module, but it may
     // be compiled into bundles that are loadable as ES modules.
     this ||
     // https://developer.mozilla.org/en-US/docs/Web/API/Window/self
     // For in-page browser environments and workers.
     self;
 
 /**
  * Builds an object structure for the provided namespace path, ensuring that
  * names that already exist are not overwritten. For example:
  * "a.b.c" -> a = {};a.b={};a.b.c={};
  * Used by goog.provide and goog.exportSymbol.
  * @param {string} name name of the object that this file defines.
  * @private
  */
 goog.exportPath_ = function(name) {
   var parts = name.split('.');
   var cur = goog.global;
 
   // Internet Explorer exhibits strange behavior when throwing errors from
   // methods externed in this manner.  See the testExportSymbolExceptions in
   // base_test.html for an example.
   if (!(parts[0] in cur) && typeof cur.execScript != 'undefined') {
     cur.execScript('var ' + parts[0]);
   }
 
   for (var part; parts.length && (part = parts.shift());) {
     if (cur[part] && cur[part] !== Object.prototype[part]) {
       cur = cur[part];
     } else {
       cur = cur[part] = {};
     }
   }
 };
 
 /**
  * Defines a namespace in Closure.
  *
  * A namespace may only be defined once in a codebase. It may be defined using
  * goog.provide() or goog.module().
  *
  * The presence of one or more goog.provide() calls in a file indicates
  * that the file defines the given objects/namespaces.
  * Provided symbols must not be null or undefined.
  *
  * In addition, goog.provide() creates the object stubs for a namespace
  * (for example, goog.provide("goog.foo.bar") will create the object
  * goog.foo.bar if it does not already exist).
  *
  * Build tools also scan for provide/require/module statements
  * to discern dependencies, build dependency files (see deps.js), etc.
  *
  * @see goog.require
  * @see goog.module
  * @param {string} name Namespace provided by this file in the form
  *     "goog.package.part".
  */
 goog.provide = function(name) {
   // Ensure that the same namespace isn't provided twice.
   // A goog.module/goog.provide maps a goog.require to a specific file
   /*
   if (goog.isProvided_(name)) {
     throw Error('Namespace "' + name + '" already declared.');
   }
 
   delete goog.implicitNamespaces_[name];
   */
 
   var namespace = name;
   while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) {
     if (goog.getObjectByName(namespace)) {
       break;
     }
     goog.implicitNamespaces_[namespace] = true;
   }
 
   goog.exportPath_(name);
 };
 
 /**
  * @private {?{
  *   moduleName: (string|undefined),
  *   declareLegacyNamespace:boolean,
  *   type: ?goog.ModuleType
  * }}
  */
 goog.moduleLoaderState_ = null;
 
 /**
  * Check if the given name has been goog.provided. This will return false for
  * names that are available only as implicit namespaces.
  * @param {string} name name of the object to look for.
  * @return {boolean} Whether the name has been provided.
  * @private
  */
 goog.isProvided_ = function(name) {
   return (!goog.implicitNamespaces_[name] &&
        goog.isDefAndNotNull(goog.getObjectByName(name)));
 };
 
 /**
  * Namespaces implicitly defined by goog.provide. For example,
  * goog.provide('goog.events.Event') implicitly declares that 'goog' and
  * 'goog.events' must be namespaces.
  *
  * @type {!Object<string, (boolean|undefined)>}
  * @private
  */
 goog.implicitNamespaces_ = {};
 
 // NOTE: We add goog.module as an implicit namespace as goog.module is defined
 // here and because the existing module package has not been moved yet out of
 // the goog.module namespace. This satisfies both the debug loader and
 // ahead-of-time dependency management.
 
 
 /**
  * Returns an object based on its fully qualified external name.  The object
  * is not found if null or undefined.  If you are using a compilation pass that
  * renames property names beware that using this function will not find renamed
  * properties.
  *
  * @param {string} name The fully qualified name.
  * @param {Object=} opt_obj The object within which to look; default is
  *     |goog.global|.
  * @return {?} The value (object or primitive) or, if not found, null.
  */
 goog.getObjectByName = function(name, opt_obj) {
   var parts = name.split('.');
   var cur = opt_obj || goog.global;
   for (var i = 0; i < parts.length; i++) {
     cur = cur[parts[i]];
     if (!goog.isDefAndNotNull(cur)) {
       return null;
     }
   }
   return cur;
 };
 
 
 /**
  * Adds a dependency from a file to the files it requires.
  * @param {string} relPath The path to the js file.
  * @param {!Array<string>} provides An array of strings with
  *     the names of the objects this file provides.
  * @param {!Array<string>} requires An array of strings with
  *     the names of the objects this file requires.
  */
 goog.addDependency = function(relPath, provides, requires) {
   goog.debugLoader_.addDependency(relPath, provides, requires);
 };
 
 
 
 
 // NOTE(nnaze): The debug DOM loader was included in base.js as an original way
 // to do "debug-mode" development.  The dependency system can sometimes be
 // confusing, as can the debug DOM loader's asynchronous nature.
 //
 // With the DOM loader, a call to goog.require() is not blocking -- the script
 // will not load until some point after the current script.  If a namespace is
 // needed at runtime, it needs to be defined in a previous script, or loaded via
 // require() with its registered dependencies.
 //
 // User-defined namespaces may need their own deps file. For a reference on
 // creating a deps file, see:
 // Externally: https://developers.google.com/closure/library/docs/depswriter
 //
 // Because of legacy clients, the DOM loader can't be easily removed from
 // base.js.  Work was done to make it disableable or replaceable for
 // different environments (DOM-less JavaScript interpreters like Rhino or V8,
 // for example). See bootstrap/ for more information.
 
 
 /**
  * Implements a system for the dynamic resolution of dependencies that works in
  * parallel with the BUILD system.
  *
  * Note that all calls to goog.require will be stripped by the compiler.
  *
  * @see goog.provide
  * @param {string} namespace Namespace (as was given in goog.provide,
  *     goog.module, or goog.declareModuleId) in the form
  *     "goog.package.part".
  * @return {?} If called within a goog.module or ES6 module file, the associated
  *     namespace or module otherwise null.
  */
 goog.require = function(namespace) {
   // If the object already exists we do not need to do anything.
   if (!goog.isProvided_(namespace)) {
     var moduleLoaderState = goog.moduleLoaderState_;
     goog.moduleLoaderState_ = null;
     try {
       goog.debugLoader_.load_(namespace);
     } finally {
       goog.moduleLoaderState_ = moduleLoaderState;
     }
   }
 
   return null;
 };
 
 /**
  * Requires a symbol for its type information. This is an indication to the
  * compiler that the symbol may appear in type annotations, yet it is not
  * referenced at runtime.
  *
  * When called within a goog.module or ES6 module file, the return value may be
  * assigned to or destructured into a variable, but it may not be otherwise used
  * in code outside of a type annotation.
  *
  * Note that all calls to goog.requireType will be stripped by the compiler.
  *
  * @param {string} namespace Namespace (as was given in goog.provide,
  *     goog.module, or goog.declareModuleId) in the form
  *     "goog.package.part".
  * @return {?}
  */
 goog.requireType = function(namespace) {
   // Return an empty object so that single-level destructuring of the return
   // value doesn't crash at runtime when using the debug loader. Multi-level
   // destructuring isn't supported.
   return {};
 };
 
 /**
  * Path for included scripts.
  * @type {string}
  */
 goog.basePath = '';
 
 /**
  * Normalize a file path by removing redundant ".." and extraneous "." file
  * path components.
  * @param {string} path
  * @return {string}
  * @private
  */
 goog.normalizePath_ = function(path) {
   var components = path.split('/');
   var i = 0;
   while (i < components.length) {
     if (components[i] == '.') {
       components.splice(i, 1);
     } else if (
         i && components[i] == '..' && components[i - 1] &&
         components[i - 1] != '..') {
       components.splice(--i, 2);
     } else {
       i++;
     }
   }
   return components.join('/');
 };
 
 
 //==============================================================================
 // Language Enhancements
 //==============================================================================
 
 
 /**
  * Returns true if the specified value is defined and not null.
  * @param {?} val Variable to test.
  * @return {boolean} Whether variable is defined and not null.
  */
 goog.isDefAndNotNull = function(val) {
   // Note that undefined == null.
   return val != null;
 };
 
 //==============================================================================
 // goog.defineClass implementation
 //==============================================================================
 
 
 // There's a bug in the compiler where without collapse properties the
 // Closure namespace defines do not guard code correctly. To help reduce code
 // size also check for !COMPILED even though it redundant until this is fixed.
 
 /**
  * Tries to detect the base path of base.js script that bootstraps Closure.
  * @private
  */
 goog.findBasePath_ = function() {
   /** @type {!Document} */
   var doc = goog.global.document;
   // If we have a currentScript available, use it exclusively.
   var currentScript = doc.currentScript;
   if (currentScript) {
     var scripts = [currentScript];
   } else {
     var scripts = doc.getElementsByTagName('SCRIPT');
   }
   // Search backwards since the current script is in almost all cases the one
   // that has base.js.
   for (var i = scripts.length - 1; i >= 0; --i) {
     var script = /** @type {!HTMLScriptElement} */ (scripts[i]);
     var src = script.src;
     var qmark = src.lastIndexOf('?');
     var l = qmark == -1 ? src.length : qmark;
     if (src.substr(l - 7, 7) == 'base.js') {
       goog.basePath = src.substr(0, l - 7);
       return;
     }
   }
 };
 
 goog.findBasePath_();
 
 /**
  * A debug loader is responsible for downloading and executing javascript
  * files in an unbundled, uncompiled environment.
  *
  * @struct @constructor @final @private
  */
 goog.DebugLoader_ = function() {
   /** @private @const {!Object<string, !goog.Dependency>} */
   this.dependencies_ = {};
   /** @private @const {!Object<string, string>} */
   this.idToPath_ = {};
   /** @private @const {!Object<string, boolean>} */
   this.written_ = {};
   /** @private {!Array<!goog.Dependency>} */
   this.depsToLoad_ = [];
 };
 
 
 /**
  * Travserses the dependency graph and queues the given dependency, and all of
  * its transitive dependencies, for loading and then starts loading if not
  * paused.
  *
  * @param {string} namespace
  * @private
  */
 goog.DebugLoader_.prototype.load_ = function(namespace) {
   if (!this.getPathFromDeps_(namespace)) {
     throw Error('goog.require could not find: ' + namespace);
   } else {
     var loader = this;
 
     var deps = [];
 
     /** @param {string} namespace */
     var visit = function(namespace) {
       var path = loader.getPathFromDeps_(namespace);
 
       if (!path) {
         throw Error('Bad dependency path or symbol: ' + namespace);
       }
 
       if (loader.written_[path]) {
         return;
       }
 
       loader.written_[path] = true;
 
       var dep = loader.dependencies_[path];
       for (var i = 0; i < dep.requires.length; i++) {
         if (!goog.isProvided_(dep.requires[i])) {
           visit(dep.requires[i]);
         }
       }
 
       deps.push(dep);
     };
 
     visit(namespace);
 
     var wasLoading = !!this.depsToLoad_.length;
     this.depsToLoad_ = this.depsToLoad_.concat(deps);
 
     if (!wasLoading) {
       this.loadDeps_();
     }
   }
 };
 
 
 /**
  * Loads any queued dependencies until they are all loaded or paused.
  *
  * @private
  */
 goog.DebugLoader_.prototype.loadDeps_ = function() {
   var loader = this;
 
   while (this.depsToLoad_.length) {
     (function() {
       var loadCallDone = false;
       var dep = loader.depsToLoad_.shift();
 
       try {
         dep.load();
       } finally {
         loadCallDone = true;
       }
     })();
   }
 };
 
 
 /**
  * @param {string} absPathOrId
  * @return {?string}
  * @private
  */
 goog.DebugLoader_.prototype.getPathFromDeps_ = function(absPathOrId) {
   return this.idToPath_[absPathOrId];
 };
 
 
 /**
  * Basic super class for all dependencies Closure Library can load.
  *
  * This default implementation is designed to load untranspiled, non-module
  * scripts in a web broswer.
  *
  * For transpiled non-goog.module files {@see goog.TranspiledDependency}.
  * For goog.modules see {@see goog.GoogModuleDependency}.
  * For untranspiled ES6 modules {@see goog.Es6ModuleDependency}.
  *
  * @param {string} path Absolute path of this script.
  * @param {!Array<string>} requires goog symbols or relative paths to Closure
  *     this depends on.
  * @struct @constructor
  */
 goog.Dependency = function(path, requires) {
   /** @const */
   this.path = path;
   /** @const */
   this.requires = requires;
 };
 
 /**
  * Map of script ready / state change callbacks. Old IE cannot handle putting
  * these properties on goog.global.
  *
  * @private @const {!Object<string, function(?):undefined>}
  */
 goog.Dependency.callbackMap_ = {};
 
 
 /**
  * Starts loading this dependency. This dependency can pause loading if it
  * needs to and resume it later via the controller interface.
  *
  * When this is loaded it should call controller.loaded(). Note that this will
  * end up calling the loaded method of this dependency; there is no need to
  * call it explicitly.
  */
 goog.Dependency.prototype.load = function() {
   /** @type {!HTMLDocument} */
   var doc = goog.global.document;
   doc.write('<script src="' + this.path + '" type="text/javascript"><' +
       '/script>');
 };
 
 
 /**
  * @param {string} relPath
  * @param {!Array<string>|undefined} provides
  * @param {!Array<string>} requires
  * @see goog.addDependency
  */
 goog.DebugLoader_.prototype.addDependency = function(
     relPath, provides, requires) {
   relPath = relPath.replace(/\\/g, '/');
   var path = goog.normalizePath_(goog.basePath + relPath);
   var dep = new goog.Dependency(path, requires);
   this.dependencies_[path] = dep;
   for (var i = 0; i < provides.length; i++) {
     this.idToPath_[provides[i]] = path;
   }
   this.idToPath_[relPath] = path;
 };
 
 
 /** @private @const */
 goog.debugLoader_ = new goog.DebugLoader_();
 