/**
 * @license
 * Copyright (C) 2019 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';

  // Import utils methods
  const {
    PLUGIN_LOADING_TIMEOUT_MS,
    PRELOADED_PROTOCOL,
    getPluginNameFromUrl,
    getBaseUrl,
  } = window._apiUtils;

  /**
   * @enum {string}
   */
  const PluginState = {
    /**
     * State that indicates the plugin is pending to be loaded.
     */
    PENDING: 'PENDING',

    /**
     * State that indicates the plugin is already loaded.
     */
    LOADED: 'LOADED',

    /**
     * State that indicates the plugin is already loaded.
     */
    PRE_LOADED: 'PRE_LOADED',

    /**
     * State that indicates the plugin failed to load.
     */
    LOAD_FAILED: 'LOAD_FAILED',
  };

  // Prefix for any unrecognized plugin urls.
  // Url should match following patterns:
  // /plugins/PLUGINNAME/static/SCRIPTNAME.(html|js)
  // /plugins/PLUGINNAME.(js|html)
  const UNKNOWN_PLUGIN_PREFIX = '__$$__';

  // Current API version for Plugin,
  // plugins with incompatible version will not be laoded.
  const API_VERSION = '0.1';

  /**
   * PluginLoader, responsible for:
   *
   * Loading all plugins and handling errors etc.
   * Recording plugin state.
   * Reporting on plugin loading status.
   * Retrieve plugin.
   * Check plugin status and if all plugins loaded.
   */
  class PluginLoader {
    constructor() {
      this._pluginListLoaded = false;

      /** @type {Map<string,PluginLoader.PluginObject>} */
      this._plugins = new Map();

      this._reporting = null;

      // Promise that resolves when all plugins loaded
      this._loadingPromise = null;

      // Resolver to resolve _loadingPromise once all plugins loaded
      this._loadingResolver = null;
    }

    _getReporting() {
      if (!this._reporting) {
        this._reporting = document.createElement('gr-reporting');
      }
      return this._reporting;
    }

    /**
     * Use the plugin name or use the full url if not recognized.
     *
     * @see gr-api-utils#getPluginNameFromUrl
     * @param {string|URL} url
     */
    _getPluginKeyFromUrl(url) {
      return getPluginNameFromUrl(url) ||
        `${UNKNOWN_PLUGIN_PREFIX}${url}`;
    }

    /**
     * Load multiple plugins with certain options.
     *
     * @param {Array<string>} plugins
     * @param {Object<string, PluginLoader.PluginOption>} opts
     */
    loadPlugins(plugins = [], opts = {}) {
      this._pluginListLoaded = true;

      plugins.forEach(path => {
        const url = this._urlFor(path);
        // Skip if preloaded, for bundling.
        if (this.isPluginPreloaded(url)) return;

        const pluginKey = this._getPluginKeyFromUrl(url);
        // Skip if already installed.
        if (this._plugins.has(pluginKey)) return;
        this._plugins.set(pluginKey, {
          name: pluginKey,
          url,
          state: PluginState.PENDING,
          plugin: null,
        });

        if (this._isPathEndsWith(url, '.html')) {
          this._importHtmlPlugin(url, opts && opts[path]);
        } else if (this._isPathEndsWith(url, '.js')) {
          this._loadJsPlugin(url);
        } else {
          this._failToLoad(`Unrecognized plugin url ${url}`, url);
        }
      });

      this.awaitPluginsLoaded().then(() => {
        console.info('Plugins loaded');
        this._getReporting().pluginsLoaded(this._getAllInstalledPluginNames());
      });
    }

    _isPathEndsWith(url, suffix) {
      if (!(url instanceof URL)) {
        try {
          url = new URL(url);
        } catch (e) {
          console.warn(e);
          return false;
        }
      }

      return url.pathname && url.pathname.endsWith(suffix);
    }

    _getAllInstalledPluginNames() {
      const installedPlugins = [];
      for (const plugin of this._plugins.values()) {
        if (plugin.state === PluginState.LOADED) {
          installedPlugins.push(plugin.name);
        }
      }
      return installedPlugins;
    }

    install(callback, opt_version, opt_src) {
      // HTML import polyfill adds __importElement pointing to the import tag.
      const script = document.currentScript &&
          (document.currentScript.__importElement || document.currentScript);
      let src = opt_src || (script && script.src);
      if (!src || src.startsWith('data:')) {
        src = script && script.baseURI;
      }

      if (opt_version && opt_version !== API_VERSION) {
        this._failToLoad(`Plugin ${src} install error: only version ` +
            API_VERSION + ' is supported in PolyGerrit. ' + opt_version +
            ' was given.', src);
        return;
      }

      const pluginObject = this.getPlugin(src);
      let plugin = pluginObject && pluginObject.plugin;
      if (!plugin) {
        plugin = new Plugin(src);
      }
      try {
        callback(plugin);
        this._pluginInstalled(src, plugin);
      } catch (e) {
        this._failToLoad(`${e.name}: ${e.message}`, src);
      }
    }

    get arePluginsLoaded() {
      // As the size of plugins is relatively small,
      // so the performance of this check should be reasonable
      if (!this._pluginListLoaded) return false;
      for (const plugin of this._plugins.values()) {
        if (plugin.state === PluginState.PENDING) return false;
      }
      return true;
    }

    _checkIfCompleted() {
      if (this.arePluginsLoaded && this._loadingResolver) {
        this._loadingResolver();
        this._loadingResolver = null;
        this._loadingPromise = null;
      }
    }

    _timeout() {
      const pendingPlugins = [];
      for (const plugin of this._plugins.values()) {
        if (plugin.state === PluginState.PENDING) {
          this._updatePluginState(plugin.url, PluginState.LOAD_FAILED);
          this._checkIfCompleted();
          pendingPlugins.push(plugin.url);
        }
      }
      return `Timeout when loading plugins: ${pendingPlugins.join(',')}`;
    }

    _failToLoad(message, pluginUrl) {
      // Show an alert with the error
      document.dispatchEvent(new CustomEvent('show-alert', {
        detail: {
          message: `Plugin install error: ${message} from ${pluginUrl}`,
        },
      }));
      this._updatePluginState(pluginUrl, PluginState.LOAD_FAILED);
      this._checkIfCompleted();
    }

    _updatePluginState(pluginUrl, state) {
      const key = this._getPluginKeyFromUrl(pluginUrl);
      if (this._plugins.has(key)) {
        this._plugins.get(key).state = state;
      } else {
        // Plugin is not recorded for some reason.
        console.warn(`Plugin loaded separately: ${pluginUrl}`);
        this._plugins.set(key, {
          name: key,
          url: pluginUrl,
          state,
          plugin: null,
        });
      }
      return this._plugins.get(key);
    }

    _pluginInstalled(url, plugin) {
      const pluginObj = this._updatePluginState(url, PluginState.LOADED);
      pluginObj.plugin = plugin;
      this._getReporting().pluginLoaded(plugin.getPluginName() || url);
      console.log(`Plugin ${plugin.getPluginName() || url} installed.`);
      this._checkIfCompleted();
    }

    installPreloadedPlugins() {
      if (!window.Gerrit || !window.Gerrit._preloadedPlugins) { return; }
      const Gerrit = window.Gerrit;
      for (const name in Gerrit._preloadedPlugins) {
        if (!Gerrit._preloadedPlugins.hasOwnProperty(name)) { continue; }
        const callback = Gerrit._preloadedPlugins[name];
        this.install(callback, API_VERSION, PRELOADED_PROTOCOL + name);
      }
    }

    isPluginPreloaded(pathOrUrl) {
      const url = this._urlFor(pathOrUrl);
      const name = getPluginNameFromUrl(url);
      if (name && window.Gerrit._preloadedPlugins) {
        return window.Gerrit._preloadedPlugins.hasOwnProperty(name);
      } else {
        return false;
      }
    }

    /**
     * Checks if given plugin path/url is enabled or not.
     *
     * @param {string} pathOrUrl
     */
    isPluginEnabled(pathOrUrl) {
      const url = this._urlFor(pathOrUrl);
      if (this.isPluginPreloaded(url)) return true;
      const key = this._getPluginKeyFromUrl(url);
      return this._plugins.has(key);
    }

    /**
     * Returns the plugin object with a given url.
     *
     * @param {string} pathOrUrl
     */
    getPlugin(pathOrUrl) {
      const key = this._getPluginKeyFromUrl(this._urlFor(pathOrUrl));
      return this._plugins.get(key);
    }

    /**
     * Checks if given plugin path/url is loaded or not.
     *
     * @param {string} pathOrUrl
     */
    isPluginLoaded(pathOrUrl) {
      const url = this._urlFor(pathOrUrl);
      const key = this._getPluginKeyFromUrl(url);
      return this._plugins.has(key) ?
        this._plugins.get(key).state === PluginState.LOADED :
        false;
    }

    _importHtmlPlugin(pluginUrl, opts = {}) {
      // onload (second param) needs to be a function. When null or undefined
      // were passed, plugins were not loaded correctly.
      (Polymer.importHref || Polymer.Base.importHref)(
          this._urlFor(pluginUrl), () => {},
          () => this._failToLoad(`${pluginUrl} import error`, pluginUrl),
          !opts.sync);
    }

    _loadJsPlugin(pluginUrl) {
      this._createScriptTag(this._urlFor(pluginUrl));
    }

    _createScriptTag(url) {
      const el = document.createElement('script');
      el.defer = true;
      el.src = url;
      el.onerror = () => this._failToLoad(`${url} load error`, url);
      return document.body.appendChild(el);
    }

    _urlFor(pathOrUrl) {
      if (!pathOrUrl) {
        return pathOrUrl;
      }
      if (pathOrUrl.startsWith(PRELOADED_PROTOCOL) ||
          pathOrUrl.startsWith('http')) {
        // Plugins are loaded from another domain or preloaded.
        return pathOrUrl;
      }
      if (!pathOrUrl.startsWith('/')) {
        pathOrUrl = '/' + pathOrUrl;
      }
      return window.location.origin + getBaseUrl() + pathOrUrl;
    }

    awaitPluginsLoaded() {
      // Resolve if completed.
      this._checkIfCompleted();

      if (this.arePluginsLoaded) {
        return Promise.resolve();
      }
      if (!this._loadingPromise) {
        let timerId;
        this._loadingPromise =
          Promise.race([
            new Promise(resolve => this._loadingResolver = resolve),
            new Promise((_, reject) => timerId = setTimeout(
                () => {
                  reject(this._timeout());
                }, PLUGIN_LOADING_TIMEOUT_MS)),
          ]).then(() => {
            if (timerId) clearTimeout(timerId);
          });
      }
      return this._loadingPromise;
    }
  }

  /**
   * @typedef {{
   *            name:string,
   *            url:string,
   *            state:PluginState,
   *            plugin:Object
   *          }}
   */
  PluginLoader.PluginObject;

  /**
   * @typedef {{
   *            sync:boolean,
   *          }}
   */
  PluginLoader.PluginOption;

  window.PluginLoader = PluginLoader;
})(window);