/**
 * @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(`${pluginUrl} import error`, pluginUrl);
        };
      }

      (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(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);