/**
 * @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';
import {changeViewIntegrationStyles} from '../../../styles/gr-change-view-integration-shared-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,
    changeViewIntegration: changeViewIntegrationStyles,
  };

  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;
  }
}
