text: // Copyright (C) 2017 The Android Open Source Project
  //
  // 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.
  (function(window) {
    'use strict';
  
    function GrPluginEndpoints() {
      this._endpoints = {};
      this._callbacks = {};
    }
  
    GrPluginEndpoints.prototype.onNewEndpoint = function(endpoint, callback) {
      if (!this._callbacks[endpoint]) {
        this._callbacks[endpoint] = [];
      }
      this._callbacks[endpoint].push(callback);
    };
  
    GrPluginEndpoints.prototype._getOrCreateModuleInfo = function(plugin,
        endpoint, type, moduleName, domHook) {
      const existingModule = this._endpoints[endpoint].find(info =>
          info.plugin === plugin &&
          info.moduleName === moduleName &&
          info.domHook === domHook
      );
      if (existingModule) {
        return existingModule;
      } else {
        const newModule = {
          moduleName,
          plugin,
          pluginUrl: plugin._url,
          type,
          domHook,
        };
        this._endpoints[endpoint].push(newModule);
        return newModule;
      }
    };
  
    GrPluginEndpoints.prototype.registerModule = function(plugin, endpoint, type,
        moduleName, domHook) {
      if (!this._endpoints[endpoint]) {
        this._endpoints[endpoint] = [];
      }
      const moduleInfo = this._getOrCreateModuleInfo(plugin, endpoint, type,
          moduleName, domHook);
      if (Gerrit._arePluginsLoaded() && this._callbacks[endpoint]) {
        this._callbacks[endpoint].forEach(callback => callback(moduleInfo));
      }
    };
  
    /**
     * Get detailed information about modules registered with an extension
     * endpoint.
     * @param {string} name Endpoint name.
     * @param {?{
     *   type: (string|undefined),
     *   moduleName: (string|undefined)
     * }} opt_options
     * @return {!Array<{
     *   moduleName: string,
     *   plugin: Plugin,
     *   pluginUrl: String,
     *   type: EndpointType,
     *   domHook: !Object
     * }>}
     */
    GrPluginEndpoints.prototype.getDetails = function(name, opt_options) {
      const type = opt_options && opt_options.type;
      const moduleName = opt_options && opt_options.moduleName;
      if (!this._endpoints[name]) {
        return [];
      }
      return this._endpoints[name]
          .filter(item => (!type || item.type === type) &&
                      (!moduleName || moduleName == item.moduleName));
    };
  
    /**
     * Get detailed module names for instantiating at the endpoint.
     * @param {string} name Endpoint name.
     * @param {?{
     *   type: (string|undefined),
     *   moduleName: (string|undefined)
     * }} opt_options
     * @return {!Array<string>}
     */
    GrPluginEndpoints.prototype.getModules = function(name, opt_options) {
      const modulesData = this.getDetails(name, opt_options);
      if (!modulesData.length) {
        return [];
      }
      return modulesData.map(m => m.moduleName);
    };
  
    /**
     * Get .html plugin URLs with element and module definitions.
     * @param {string} name Endpoint name.
     * @param {?{
     *   type: (string|undefined),
     *   moduleName: (string|undefined)
     * }} opt_options
     * @return {!Array<!URL>}
     */
    GrPluginEndpoints.prototype.getPlugins = function(name, opt_options) {
      const modulesData =
            this.getDetails(name, opt_options).filter(
                data => data.pluginUrl.pathname.includes('.html'));
      if (!modulesData.length) {
        return [];
      }
      return Array.from(new Set(modulesData.map(m => m.pluginUrl)));
    };
  
    window.GrPluginEndpoints = GrPluginEndpoints;
  })(window);
  