// Copyright (C) 2016 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';

  const warnNotSupported = function(opt_name) {
    console.warn('Plugin API method ' + (opt_name || '') + ' is not supported');
  };

  const stubbedMethods = ['_loadedGwt', 'screen', 'settingsScreen', 'panel'];
  const GWT_PLUGIN_STUB = {};
  for (const name of stubbedMethods) {
    GWT_PLUGIN_STUB[name] = warnNotSupported.bind(null, name);
  }

  let _restAPI;
  const getRestAPI = () => {
    if (!_restAPI) {
      _restAPI = document.createElement('gr-rest-api-interface');
    }
    return _restAPI;
  };

  const API_VERSION = '0.1';

  const EndpointType = {
    STYLE: 'style',
    DOM_DECORATION: 'dom',
  };

  // GWT JSNI uses $wnd to refer to window.
  // http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJSNI.html
  window.$wnd = window;

  function Plugin(opt_url) {
    this._generatedHookNames = [];
    this._hooks = [];

    if (!opt_url) {
      console.warn('Plugin not being loaded from /plugins base path.',
          'Unable to determine name.');
      return;
    }

    this._url = new URL(opt_url);
    if (!this._url.pathname.startsWith('/plugins')) {
      console.warn('Plugin not being loaded from /plugins base path:',
          this._url.href, '— Unable to determine name.');
      return;
    }
    this._name = this._url.pathname.split('/')[2];
  }

  Plugin._sharedAPIElement = document.createElement('gr-js-api-interface');

  Plugin.prototype._name = '';

  Plugin.prototype.getPluginName = function() {
    return this._name;
  };

  Plugin.prototype.registerStyleModule = function(endpointName, moduleName) {
    this._registerEndpointModule(
        endpointName, EndpointType.STYLE, moduleName);
  };

  Plugin.prototype.registerCustomComponent =
      function(endpointName, moduleName) {
        this._registerEndpointModule(
            endpointName, EndpointType.DOM_DECORATION, moduleName);
      };

  Plugin.prototype._registerEndpointModule = function(endpoint, type, module) {
    const endpoints = Gerrit._endpoints;
    if (!endpoints[endpoint]) {
      endpoints[endpoint] = [];
    }
    endpoints[endpoint].push({
      moduleName: module,
      plugin: this,
      pluginUrl: this._url,
      type,
    });
  };

  Plugin.prototype.getServerInfo = function() {
    return document.createElement('gr-rest-api-interface').getConfig();
  };

  Plugin.prototype.on = function(eventName, callback) {
    Plugin._sharedAPIElement.addEventCallback(eventName, callback);
  };

  Plugin.prototype.url = function(opt_path) {
    return this._url.origin + '/plugins/' + this._name + (opt_path || '/');
  };

  Plugin.prototype._send = function(method, url, opt_callback, opt_payload) {
    return getRestAPI().send(method, url, opt_payload).then(response => {
      if (response.status < 200 || response.status >= 300) {
        return response.text().then(text => {
          if (text) {
            return Promise.reject(text);
          } else {
            return Promise.reject(response.status);
          }
        });
      } else {
        return getRestAPI().getResponseObject(response);
      }
    }).then(response => {
      if (opt_callback) {
        opt_callback(response);
      }
      return response;
    });
  };

  Plugin.prototype.get = function(url, opt_callback) {
    return this._send('GET', url, opt_callback);
  },

  Plugin.prototype.post = function(url, payload, opt_callback) {
    return this._send('POST', url, opt_callback, payload);
  },

  Plugin.prototype.changeActions = function() {
    return new GrChangeActionsInterface(Plugin._sharedAPIElement.getElement(
        Plugin._sharedAPIElement.Element.CHANGE_ACTIONS));
  };

  Plugin.prototype.changeReply = function() {
    return new GrChangeReplyInterface(this,
      Plugin._sharedAPIElement.getElement(
          Plugin._sharedAPIElement.Element.REPLY_DIALOG));
  };

  Plugin.prototype._getGeneratedHookName = function(endpointName) {
    if (!this._generatedHookNames[endpointName]) {
      this._generatedHookNames[endpointName] =
        (this.getPluginName() || 'test') + '-autogenerated-' + endpointName;
    }
    return this._generatedHookNames[endpointName];
  };

  Plugin.prototype.getDomHook = function(endpointName) {
    const hookName = this._getGeneratedHookName(endpointName);
    if (!this._hooks[hookName]) {
      this._hooks[hookName] = new Promise((resolve, reject) => {
        Polymer({
          is: hookName,
          properties: {
            plugin: Object,
            content: Object,
          },
          attached() {
            resolve(this);
          },
        });
        this.registerCustomComponent(endpointName, hookName);
      });
    }
    return this._hooks[hookName];
  };

  const Gerrit = window.Gerrit || {};

  // Number of plugins to initialize, -1 means 'not yet known'.
  Gerrit._pluginsPending = -1;

  // Hash of custom components to be instantiated for extension endpoints.
  Gerrit._endpoints = {};

  Gerrit.getPluginName = function() {
    console.warn('Gerrit.getPluginName is not supported in PolyGerrit.',
        'Please use self.getPluginName() instead.');
  };

  Gerrit.css = function(rulesStr) {
    if (!Gerrit._customStyleSheet) {
      const styleEl = document.createElement('style');
      document.head.appendChild(styleEl);
      Gerrit._customStyleSheet = styleEl.sheet;
    }

    const name = '__pg_js_api_class_' +
        Gerrit._customStyleSheet.cssRules.length;
    Gerrit._customStyleSheet.insertRule('.' + name + '{' + rulesStr + '}', 0);
    return name;
  };

  Gerrit.install = function(callback, opt_version, opt_src) {
    if (opt_version && opt_version !== API_VERSION) {
      console.warn('Only version ' + API_VERSION +
          ' is supported in PolyGerrit. ' + opt_version + ' was given.');
      Gerrit._pluginInstalled();
      return;
    }

    // TODO(andybons): Polyfill currentScript for IE10/11 (edge supports it).
    const src = opt_src || (document.currentScript &&
         document.currentScript.src || document.currentScript.baseURI);
    const plugin = new Plugin(src);
    try {
      callback(plugin);
    } catch (e) {
      console.warn(plugin.getPluginName() + ' install failed: ' +
          e.name + ': ' + e.message);
    }
    Gerrit._pluginInstalled();
  };

  Gerrit.getLoggedIn = function() {
    return document.createElement('gr-rest-api-interface').getLoggedIn();
  };

  /**
   * Polyfill GWT API dependencies to avoid runtime exceptions when loading
   * GWT-compiled plugins.
   * @deprecated Not supported in PolyGerrit.
   */
  Gerrit.installGwt = function() {
    Gerrit._pluginInstalled();
    return GWT_PLUGIN_STUB;
  };

  Gerrit._allPluginsPromise = null;
  Gerrit._resolveAllPluginsLoaded = null;

  Gerrit.awaitPluginsLoaded = function() {
    if (!Gerrit._allPluginsPromise) {
      if (Gerrit._arePluginsLoaded()) {
        Gerrit._allPluginsPromise = Promise.resolve();
      } else {
        Gerrit._allPluginsPromise = new Promise(resolve => {
          Gerrit._resolveAllPluginsLoaded = resolve;
        });
      }
    }
    return Gerrit._allPluginsPromise;
  };

  Gerrit._setPluginsCount = function(count) {
    Gerrit._pluginsPending = count;
    if (Gerrit._arePluginsLoaded()) {
      document.createElement('gr-reporting').pluginsLoaded();
      if (Gerrit._resolveAllPluginsLoaded) {
        Gerrit._resolveAllPluginsLoaded();
      }
    }
  };

  Gerrit._pluginInstalled = function() {
    Gerrit._setPluginsCount(Gerrit._pluginsPending - 1);
  };

  Gerrit._arePluginsLoaded = function() {
    return Gerrit._pluginsPending === 0;
  };

  /**
   * 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 {{
   *   moduleName: string,
   *   plugin: Plugin,
   *   pluginUrl: String,
   *   type: EndpointType,
   * }}
   */
  Gerrit._getEndpointDetails = function(name, opt_options) {
    const type = opt_options && opt_options.type;
    const moduleName = opt_options && opt_options.moduleName;
    if (!Gerrit._endpoints[name]) {
      return [];
    }
    return Gerrit._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>}
   */
  Gerrit._getModulesForEndoint = function(name, opt_options) {
    const modulesData = Gerrit._getEndpointDetails(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>}
   */
  Gerrit._getPluginsForEndpoint = function(name, opt_options) {
    const modulesData =
          Gerrit._getEndpointDetails(name, opt_options).filter(
              data => data.pluginUrl.pathname.indexOf('.html') !== -1);
    if (!modulesData.length) {
      return [];
    }
    return Array.from(new Set(modulesData.map(m => m.pluginUrl)));
  };

  window.Gerrit = Gerrit;
})(window);
