/**
 * @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, window.ASSETS_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(path, opts && opts[path]);
        } else if (this._isPathEndsWith(url, '.js')) {
          this._loadJsPlugin(path);
        } else {
          this._failToLoad(`Unrecognized plugin path ${path}`, path);
        }
      });

      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 url = this._urlFor(src);
      const pluginObject = this.getPlugin(url);
      let plugin = pluginObject && pluginObject.plugin;
      if (!plugin) {
        plugin = new Plugin(url);
      }
      try {
        callback(plugin);
        this._pluginInstalled(url, 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 = {}) {
      const urlWithAP = this._urlFor(pluginUrl, window.ASSETS_PATH);
      const urlWithoutAP = this._urlFor(pluginUrl);
      let onerror = null;
      if (urlWithAP !== urlWithoutAP) {
        onerror = () => this._loadHtmlPlugin(urlWithoutAP, opts.sync);
      }
      this._loadHtmlPlugin(urlWithAP, opts.sync, onerror);
    }

    _loadHtmlPlugin(url, sync, onerror) {
      if (!onerror) {
        onerror = () => {
          this._failToLoad(`${url} import error`, url);
        };
      }

      (Polymer.importHref || Polymer.Base.importHref)(
          url, () => {},
          onerror,
          !sync);
    }

    _loadJsPlugin(pluginUrl) {
      const urlWithAP = this._urlFor(pluginUrl, window.ASSETS_PATH);
      const urlWithoutAP = this._urlFor(pluginUrl);
      let onerror = null;
      if (urlWithAP !== urlWithoutAP) {
        onerror = () => this._createScriptTag(urlWithoutAP);
      }

      this._createScriptTag(urlWithAP, onerror);
    }

    _createScriptTag(url, onerror) {
      if (!onerror) {
        onerror = () => this._failToLoad(`${url} load error`, url);
      }

      const el = document.createElement('script');
      el.defer = true;
      el.setAttribute('src', url);
      el.onerror = onerror;
      return document.body.appendChild(el);
    }

    _urlFor(pathOrUrl, assetsPath) {
      if (!pathOrUrl) {
        return pathOrUrl;
      }

      // theme is per host, should always load from assetsPath
      const isThemeFile = pathOrUrl.endsWith('static/gerrit-theme.html');
      const shouldTryLoadFromAssetsPathFirst = !isThemeFile && assetsPath;
      if (pathOrUrl.startsWith(PRELOADED_PROTOCOL) ||
          pathOrUrl.startsWith('http')) {
        // Plugins are loaded from another domain or preloaded.
        if (pathOrUrl.includes(location.host) &&
          shouldTryLoadFromAssetsPathFirst) {
          // if is loading from host server, try replace with cdn when assetsPath provided
          return pathOrUrl
              .replace(location.origin, assetsPath);
        }
        return pathOrUrl;
      }

      if (!pathOrUrl.startsWith('/')) {
        pathOrUrl = '/' + pathOrUrl;
      }

      if (shouldTryLoadFromAssetsPathFirst) {
        return assetsPath + 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(new Error(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);