/**
 * @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);