/**
 * @license
 * Copyright 2019 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import {
  getPluginNameFromUrl,
  isThemeFile,
  PLUGIN_LOADING_TIMEOUT_MS,
  THEME_JS,
} from './gr-api-utils';
import {Plugin} from './gr-public-js-api';
import {getBaseUrl} from '../../../utils/url-util';
import {GrPluginEndpoints} from './gr-plugin-endpoints';
import {PluginApi} from '../../../api/plugin';
import {ReportingService} from '../../../services/gr-reporting/gr-reporting';
import {fireAlert} from '../../../utils/event-util';
import {JsApiService} from './gr-js-api-types';
import {RestApiService} from '../../../services/gr-rest-api/gr-rest-api';
import {PluginsModel} from '../../../models/plugins/plugins-model';
import {Gerrit} from '../../../api/gerrit';
import {fontStyles} from '../../../styles/gr-font-styles';
import {grFormStyles} from '../../../styles/gr-form-styles';
import {menuPageStyles} from '../../../styles/gr-menu-page-styles';
import {spinnerStyles} from '../../../styles/gr-spinner-styles';
import {subpageStyles} from '../../../styles/gr-subpage-styles';
import {tableStyles} from '../../../styles/gr-table-styles';
import {GrJsApiInterface} from './gr-js-api-interface-element';
import {define} from '../../../models/dependency';
import {modalStyles} from '../../../styles/gr-modal-styles';
import {Finalizable} from '../../../types/types';
import {materialStyles} from '../../../styles/gr-material-styles';

enum 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 failed to load. */
  LOAD_FAILED = 'LOAD_FAILED',
}

interface PluginObject {
  name: string;
  url: string;
  state: PluginState;
  plugin: PluginApi | null;
}

interface PluginOption {
  sync?: boolean;
}

export interface PluginOptionMap {
  [path: string]: PluginOption;
}

type GerritScriptElement = HTMLScriptElement & {
  __importElement: HTMLScriptElement;
};

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

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

export const pluginLoaderToken = define<PluginLoader>('plugin-loader');

/**
 * 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.
 */
export class PluginLoader implements Gerrit, Finalizable {
  public readonly styles = {
    font: fontStyles,
    form: grFormStyles,
    material: materialStyles,
    menuPage: menuPageStyles,
    spinner: spinnerStyles,
    subPage: subpageStyles,
    table: tableStyles,
    modal: modalStyles,
  };

  private pluginListLoaded = false;

  private plugins = new Map<string, PluginObject>();

  // Promise that resolves when all plugins loaded
  private loadingPromise: Promise<void> | null = null;

  // Resolver to resolve loadingPromise once all plugins loaded
  private loadingResolver: (() => void) | null = null;

  private instanceId?: string;

  public readonly jsApiService: JsApiService;

  public readonly pluginsModel: PluginsModel;

  public pluginEndPoints: GrPluginEndpoints;

  constructor(
    private readonly reportingService: ReportingService,
    private readonly restApiService: RestApiService
  ) {
    this.jsApiService = new GrJsApiInterface(
      () => this.awaitPluginsLoaded(),
      this.reportingService
    );
    this.pluginsModel = new PluginsModel();
    this.awaitPluginsLoaded().finally(() => {
      this.pluginsModel.updateState({pluginsLoaded: true});
    });
    this.pluginEndPoints = new GrPluginEndpoints();
  }

  finalize() {}

  /**
   * Use the plugin name or use the full url if not recognized.
   */
  private getPluginKeyFromUrl(url: string) {
    return getPluginNameFromUrl(url) || `${UNKNOWN_PLUGIN_PREFIX}${url}`;
  }

  /**
   * Load multiple plugins with certain options.
   */
  loadPlugins(plugins: string[] = [], instanceId?: string) {
    this.instanceId = instanceId;
    this.pluginListLoaded = true;

    plugins.forEach(path => {
      const url = this.urlFor(path, window.ASSETS_PATH);
      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, '.js')) {
        this.loadJsPlugin(path);
      } else {
        this.failToLoad(`Unrecognized plugin path ${path}`, path);
      }
    });

    this.awaitPluginsLoaded().then(() => {
      const loaded = this.getPluginsByState(PluginState.LOADED);
      const failed = this.getPluginsByState(PluginState.LOAD_FAILED);
      this.reportingService.pluginsLoaded(loaded.map(p => p.name));
      this.reportingService.pluginsFailed(failed.map(p => p.name));
    });
  }

  private isPathEndsWith(url: string | URL, suffix: string) {
    if (!(url instanceof URL)) {
      try {
        url = new URL(url);
      } catch (e: unknown) {
        this.reportingService.error(
          'GrPluginLoader',
          new Error('url parse error'),
          e
        );
        return false;
      }
    }

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

  private getPluginsByState(state: PluginState) {
    return [...this.plugins.values()].filter(p => p.state === state);
  }

  install(
    callback: (plugin: PluginApi) => void,
    version?: string,
    src?: string
  ) {
    // HTML import polyfill adds __importElement pointing to the import tag.
    const gerritScript = document.currentScript as GerritScriptElement | null;
    const script = gerritScript?.__importElement ?? gerritScript;
    if (!src && script && script.src) {
      src = script.src;
    }
    if ((!src || src.startsWith('data:')) && script && script.baseURI) {
      src = script && script.baseURI;
    }
    if (!src) {
      this.failToLoad('Failed to determine src.');
      return;
    }
    if (version && version !== API_VERSION) {
      this.failToLoad(
        `Plugin ${src} install error: only version ${API_VERSION} is supported in PolyGerrit. ${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,
        this.jsApiService,
        this.reportingService,
        this.restApiService,
        this.pluginsModel,
        this.pluginEndPoints
      );
    }
    try {
      callback(plugin);
      this.pluginInstalled(url, plugin);
    } catch (e: unknown) {
      if (e instanceof Error) {
        this.failToLoad(`${e.name}: ${e.message}`, src);
      } else {
        this.reportingService.error(
          'GrPluginLoader',
          new Error('plugin callback error'),
          e
        );
      }
    }
  }

  arePluginsLoaded() {
    if (!this.pluginListLoaded) return false;
    return this.getPluginsByState(PluginState.PENDING).length === 0;
  }

  private checkIfCompleted() {
    if (this.arePluginsLoaded()) {
      this.pluginEndPoints.setPluginsReady();
      if (this.loadingResolver) {
        this.loadingResolver();
        this.loadingResolver = null;
        this.loadingPromise = null;
      }
    }
  }

  private timeout() {
    const pending = this.getPluginsByState(PluginState.PENDING);
    for (const plugin of pending) {
      this.updatePluginState(plugin.url, PluginState.LOAD_FAILED);
    }
    this.checkIfCompleted();
    const errorMessage = `Timeout when loading plugins: ${pending
      .map(p => p.name)
      .join(',')}`;
    fireAlert(document, errorMessage);
    return errorMessage;
  }

  // Private but mocked in tests.
  failToLoad(message: string, pluginUrl?: string) {
    // Show an alert with the error
    fireAlert(document, `Plugin install error: ${message} from ${pluginUrl}`);
    if (pluginUrl) this.updatePluginState(pluginUrl, PluginState.LOAD_FAILED);
    this.checkIfCompleted();
  }

  private updatePluginState(
    pluginUrl: string,
    state: PluginState
  ): PluginObject {
    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.info(`Plugin loaded separately: ${pluginUrl}`);
      this.plugins.set(key, {
        name: key,
        url: pluginUrl,
        state,
        plugin: null,
      });
    }
    console.debug(`Plugin ${key} ${state}`);
    return this.plugins.get(key)!;
  }

  private pluginInstalled(url: string, plugin: PluginApi) {
    const pluginObj = this.updatePluginState(url, PluginState.LOADED);
    pluginObj.plugin = plugin;
    this.reportingService.pluginLoaded(plugin.getPluginName() || url);
    this.checkIfCompleted();
  }

  /**
   * Checks if given plugin path/url is enabled or not.
   */
  isPluginEnabled(pathOrUrl: string) {
    const url = this.urlFor(pathOrUrl);
    const key = this.getPluginKeyFromUrl(url);
    return this.plugins.has(key);
  }

  /**
   * Returns the plugin object with a given url.
   */
  getPlugin(pathOrUrl: string) {
    const url = this.urlFor(pathOrUrl);
    const key = this.getPluginKeyFromUrl(url);
    return this.plugins.get(key);
  }

  /**
   * Checks if given plugin path/url is loaded or not.
   */
  isPluginLoaded(pathOrUrl: string): boolean {
    const url = this.urlFor(pathOrUrl);
    const key = this.getPluginKeyFromUrl(url);
    return this.plugins.has(key)
      ? this.plugins.get(key)!.state === PluginState.LOADED
      : false;
  }

  // Private but mocked in tests.
  loadJsPlugin(pluginUrl: string) {
    const urlWithAP = this.urlFor(pluginUrl, window.ASSETS_PATH);
    const urlWithoutAP = this.urlFor(pluginUrl);
    let onerror = undefined;
    if (urlWithAP !== urlWithoutAP) {
      onerror = () => this.createScriptTag(urlWithoutAP);
    }

    this.createScriptTag(urlWithAP, onerror);
  }

  // Private but mocked in tests.
  createScriptTag(url: string, onerror?: OnErrorEventHandler) {
    if (!onerror) {
      onerror = () => this.failToLoad(`${url} load error`, url);
    }

    const el = document.createElement('script');
    el.defer = true;
    el.setAttribute('src', url);
    // no credentials to send when fetch plugin js
    // and this will help provide more meaningful error than
    // 'Script error.'
    el.setAttribute('crossorigin', 'anonymous');
    el.onerror = onerror;
    return document.body.appendChild(el);
  }

  private urlFor(pathOrUrl: string, assetsPath?: string): string {
    if (isThemeFile(pathOrUrl)) {
      if (assetsPath && this.instanceId) {
        return `${assetsPath}/hosts/${this.instanceId}${THEME_JS}`;
      }
      return window.location.origin + getBaseUrl() + THEME_JS;
    }

    if (pathOrUrl.startsWith('http')) {
      // Plugins are loaded from another domain or preloaded.
      if (pathOrUrl.includes(location.host) && assetsPath) {
        // 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 (assetsPath) {
      return assetsPath + pathOrUrl;
    }
    return window.location.origin + getBaseUrl() + pathOrUrl;
  }

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

    if (this.arePluginsLoaded()) {
      return Promise.resolve();
    }
    if (!this.loadingPromise) {
      // specify window here so that TS pulls the correct setTimeout method
      // if window is not specified, then the function is pulled from node
      // and the return type is NodeJS.Timeout object
      let timerId: number;
      this.loadingPromise = Promise.race([
        new Promise<void>(resolve => (this.loadingResolver = resolve)),
        new Promise(
          (_, reject) =>
            (timerId = window.setTimeout(() => {
              reject(new Error(this.timeout()));
            }, PLUGIN_LOADING_TIMEOUT_MS))
        ),
      ]).finally(() => {
        if (timerId) clearTimeout(timerId);
      }) as Promise<void>;
    }
    return this.loadingPromise;
  }
}
