/**
 * @license
 * Copyright 2020 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import {
  AttemptChoice,
  AttemptDetail,
  createAttemptMap,
  LATEST_ATTEMPT,
  sortAttemptDetails,
} from './checks-util';
import {assertIsDefined} from '../../utils/common-util';
import {select} from '../../utils/observable-util';
import {
  BehaviorSubject,
  combineLatest,
  from,
  Observable,
  of,
  Subject,
  timer,
} from 'rxjs';
import {
  catchError,
  filter,
  switchMap,
  take,
  takeUntil,
  takeWhile,
  timeout,
  throttleTime,
  withLatestFrom,
} from 'rxjs/operators';
import {
  Action,
  CheckResult as CheckResultApi,
  CheckRun as CheckRunApi,
  Link,
  ChangeData,
  ChecksApiConfig,
  ChecksProvider,
  FetchResponse,
  ResponseCode,
  Category,
  RunStatus,
} from '../../api/checks';
import {ChangeModel} from '../change/change-model';
import {ChangeInfo, NumericChangeId, PatchSetNumber} from '../../types/common';
import {getCurrentRevision} from '../../utils/change-util';
import {getShaByPatchNum} from '../../utils/patch-set-util';
import {ReportingService} from '../../services/gr-reporting/gr-reporting';
import {Execution, Interaction, Timing} from '../../constants/reporting';
import {fireAlert, fireEvent} from '../../utils/event-util';
import {Model} from '../model';
import {define} from '../dependency';
import {
  ChecksPlugin,
  ChecksUpdate,
  PluginsModel,
} from '../plugins/plugins-model';
import {ChangeViewModel} from '../views/change';

/**
 * The checks model maintains the state of checks for two patchsets: the latest
 * and (if different) also for the one selected in the checks tab. So we need
 * the distinction in a lot of places for checks about whether the code affects
 * the checks data of the LATEST or the SELECTED patchset.
 */
export enum ChecksPatchset {
  LATEST = 'LATEST',
  SELECTED = 'SELECTED',
}

export interface CheckResult extends CheckResultApi {
  /**
   * Internally we want to uniquely identify a run with an id, for example when
   * efficiently re-rendering lists of runs in the UI.
   */
  internalResultId: string;
}

export interface CheckRun extends CheckRunApi {
  /**
   * For convenience we attach the name of the plugin to each run.
   */
  pluginName: string;
  /**
   * Internally we want to uniquely identify a result with an id, for example
   * when efficiently re-rendering lists of results in the UI.
   */
  internalRunId: string;
  /**
   * Is this run attempt the latest attempt for the check, i.e. does it have
   * the highest attempt number among all checks with the same name?
   */
  isLatestAttempt: boolean;
  /**
   * Is this the only attempt for the check, i.e. we don't have data for other
   * attempts?
   */
  isSingleAttempt: boolean;
  /**
   * List of all attempts for the same check, ordered by attempt number.
   */
  attemptDetails: AttemptDetail[];
  results?: CheckResult[];
}

// This is a convenience type for working with results, because when working
// with a bunch of results you will typically also want to know about the run
// properties. So you can just combine them with {...run, ...result}.
export type RunResult = CheckRun & CheckResult;

export const checksModelToken = define<ChecksModel>('checks-model');

export interface ChecksProviderState {
  pluginName: string;
  loading: boolean;
  /**
   * Allows to distinguish whether loading:true is the *first* time of loading
   * something for this provider. Or just a subsequent background update.
   * Note that this is initially true even before loading is being set to true,
   * so you may want to check loading && firstTimeLoad.
   */
  firstTimeLoad: boolean;
  /** Presence of errorMessage implicitly means that the provider is in ERROR state. */
  errorMessage?: string;
  /** Presence of loginCallback implicitly means that the provider is in NOT_LOGGED_IN state. */
  loginCallback?: () => void;
  summaryMessage?: string;
  runs: CheckRun[];
  actions: Action[];
  links: Link[];
}

interface ChecksState {
  /** Checks data for the latest patchset. */
  pluginStateLatest: {
    [name: string]: ChecksProviderState;
  };
  /**
   * Checks data for the selected patchset. Note that `checksSelected$` below
   * falls back to the data for the latest patchset, if no patchset is selected.
   */
  pluginStateSelected: {
    [name: string]: ChecksProviderState;
  };
}

/**
 * Android's Checks Plugin has a 15s timeout internally. So we are using
 * something slightly larger, so that we get a proper error from the plugin,
 * if they run into timeout issues.
 */
const FETCH_RESULT_TIMEOUT_MS = 16000;

/**
 * Can be used in `reduce()` to collect all results from all runs from all
 * providers into one array.
 */
function collectRunResults(
  allResults: RunResult[],
  providerState: ChecksProviderState
) {
  return [
    ...allResults,
    ...providerState.runs.reduce((results: RunResult[], run: CheckRun) => {
      const runResults: RunResult[] =
        run.results?.map(r => {
          return {...run, ...r};
        }) ?? [];
      return results.concat(runResults ?? []);
    }, []),
  ];
}

export interface ErrorMessages {
  /* Maps plugin name to error message. */
  [name: string]: string;
}

export class ChecksModel extends Model<ChecksState> {
  private readonly providers: {[name: string]: ChecksProvider} = {};

  private readonly reloadSubjects: {[name: string]: Subject<void>} = {};

  private checkToPluginMap = new Map<string, string>();

  // visible for testing
  changeNum?: NumericChangeId;

  // visible for testing
  latestPatchNum?: PatchSetNumber;

  private readonly documentVisibilityChange$ = new BehaviorSubject(undefined);

  private readonly reloadListener: () => void;

  private readonly visibilityChangeListener: () => void;

  public checksSelectedPatchsetNumber$ = select(
    this.changeViewModel.checksPatchset$,
    ps => ps
  );

  public checksSelectedAttemptNumber$ = select(
    this.changeViewModel.attempt$,
    attempt => attempt ?? LATEST_ATTEMPT
  );

  public runFilterRegexp$ = select(
    this.changeViewModel.filter$,
    filter => filter ?? ''
  );

  public checksLatest$ = select(this.state$, state => state.pluginStateLatest);

  public checksSelected$ = select(
    combineLatest([this.state$, this.changeViewModel.checksPatchset$]),
    ([state, ps]) => {
      const checksPs = ps ? ChecksPatchset.SELECTED : ChecksPatchset.LATEST;
      return this.getPluginState(state, checksPs);
    }
  );

  public aPluginHasRegistered$ = select(
    this.checksLatest$,
    state => Object.keys(state).length > 0
  );

  private firstLoadCompleted$ = select(this.checksLatest$, state => {
    const providers = Object.values(state);
    if (providers.length === 0) return false;
    if (providers.some(p => p.loading || p.firstTimeLoad)) return false;
    return true;
  });

  public someProvidersAreLoadingFirstTime$ = select(this.checksLatest$, state =>
    Object.values(state).some(
      provider => provider.loading && provider.firstTimeLoad
    )
  );

  public someProvidersAreLoadingLatest$ = select(this.checksLatest$, state =>
    Object.values(state).some(providerState => providerState.loading)
  );

  public someProvidersAreLoadingSelected$ = select(
    this.checksSelected$,
    state => Object.values(state).some(providerState => providerState.loading)
  );

  public errorMessageLatest$ = select(
    this.checksLatest$,

    state =>
      Object.values(state).find(
        providerState => providerState.errorMessage !== undefined
      )?.errorMessage
  );

  public errorMessagesLatest$ = select(this.checksLatest$, state => {
    const errorMessages: ErrorMessages = {};
    for (const providerState of Object.values(state)) {
      if (providerState.errorMessage === undefined) continue;
      errorMessages[providerState.pluginName] = providerState.errorMessage;
    }
    return errorMessages;
  });

  public loginCallbackLatest$ = select(
    this.checksLatest$,
    state =>
      Object.values(state).find(
        providerState => providerState.loginCallback !== undefined
      )?.loginCallback
  );

  public topLevelActionsLatest$ = select(this.checksLatest$, state =>
    Object.values(state).reduce(
      (allActions: Action[], providerState: ChecksProviderState) => [
        ...allActions,
        ...providerState.actions,
      ],
      []
    )
  );

  public topLevelMessagesLatest$ = select(this.checksLatest$, state => {
    const messages = Object.values(state).map(
      providerState => providerState.summaryMessage
    );
    return messages.filter(m => !!m) as string[];
  });

  public topLevelActionsSelected$ = select(this.checksSelected$, state =>
    Object.values(state).reduce(
      (allActions: Action[], providerState: ChecksProviderState) => [
        ...allActions,
        ...providerState.actions,
      ],
      []
    )
  );

  public topLevelLinksSelected$ = select(this.checksSelected$, state =>
    Object.values(state).reduce(
      (allLinks: Link[], providerState: ChecksProviderState) => [
        ...allLinks,
        ...providerState.links,
      ],
      []
    )
  );

  public allRunsLatestPatchset$ = select(this.checksLatest$, state =>
    Object.values(state).reduce(
      (allRuns: CheckRun[], providerState: ChecksProviderState) => [
        ...allRuns,
        ...providerState.runs,
      ],
      []
    )
  );

  public allRunsSelectedPatchset$ = select(this.checksSelected$, state =>
    Object.values(state).reduce(
      (allRuns: CheckRun[], providerState: ChecksProviderState) => [
        ...allRuns,
        ...providerState.runs,
      ],
      []
    )
  );

  public allRunsLatestPatchsetLatestAttempt$ = select(
    this.allRunsLatestPatchset$,
    runs => runs.filter(run => run.isLatestAttempt)
  );

  public checkToPluginMap$ = select(this.checksLatest$, state => {
    const map = new Map<string, string>();
    for (const [pluginName, providerState] of Object.entries(state)) {
      for (const run of providerState.runs) {
        map.set(run.checkName, pluginName);
      }
    }
    return map;
  });

  public allResultsSelected$ = select(this.checksSelected$, state =>
    Object.values(state)
      .reduce(collectRunResults, [])
      .filter(r => r !== undefined)
  );

  public allResultsLatest$ = select(this.checksLatest$, state =>
    Object.values(state)
      .reduce(collectRunResults, [])
      .filter(r => r !== undefined)
  );

  public allResults$ = select(
    combineLatest([
      this.checksSelectedPatchsetNumber$,
      this.allResultsSelected$,
      this.allResultsLatest$,
    ]),
    ([selectedPs, selected, latest]) =>
      selectedPs ? [...selected, ...latest] : latest
  );

  constructor(
    private readonly changeViewModel: ChangeViewModel,
    private readonly changeModel: ChangeModel,
    private readonly reporting: ReportingService,
    private readonly pluginsModel: PluginsModel
  ) {
    super({
      pluginStateLatest: {},
      pluginStateSelected: {},
    });
    this.reporting.time(Timing.CHECKS_LOAD);
    this.subscriptions = [
      this.changeModel.changeNum$.subscribe(x => (this.changeNum = x)),
      this.changeModel.latestPatchNum$.subscribe(
        x => (this.latestPatchNum = x)
      ),
      this.pluginsModel.checksPlugins$.subscribe(plugins => {
        for (const plugin of plugins) {
          this.register(plugin);
        }
      }),
      this.pluginsModel.checksAnnounce$.subscribe(a =>
        this.reload(a.pluginName)
      ),
      this.pluginsModel.checksUpdate$.subscribe(u => this.updateResult(u)),
      this.checkToPluginMap$.subscribe(map => {
        this.checkToPluginMap = map;
      }),
      this.firstLoadCompleted$
        .pipe(
          filter(completed => !!completed),
          take(1),
          withLatestFrom(this.checksLatest$)
        )
        .subscribe(([_, state]) => this.reportStats(state)),
    ];
    this.visibilityChangeListener = () => {
      this.documentVisibilityChange$.next(undefined);
    };
    document.addEventListener(
      'visibilitychange',
      this.visibilityChangeListener
    );
    this.reloadListener = () => this.reloadAll();
    document.addEventListener('reload', this.reloadListener);
  }

  private reportStats(state: {[name: string]: ChecksProviderState}) {
    const stats = {
      providerCount: 0,
      providerErrorCount: 0,
      providerLoginCount: 0,
      providerActionCount: 0,
      providerLinkCount: 0,
      errorCount: 0,
      warningCount: 0,
      infoCount: 0,
      successCount: 0,
      runnableCount: 0,
      scheduledCount: 0,
      runningCount: 0,
      completedCount: 0,
    };
    const providers = Object.values(state);
    for (const provider of providers) {
      stats.providerCount++;
      if (provider.errorMessage) stats.providerErrorCount++;
      if (provider.loginCallback) stats.providerLoginCount++;
      if (provider.actions?.length) stats.providerActionCount++;
      if (provider.links?.length) stats.providerLinkCount++;
      for (const run of provider.runs) {
        if (run.status === RunStatus.RUNNABLE) stats.runnableCount++;
        if (run.status === RunStatus.SCHEDULED) stats.scheduledCount++;
        if (run.status === RunStatus.RUNNING) stats.runningCount++;
        if (run.status === RunStatus.COMPLETED) stats.completedCount++;
        for (const result of run.results ?? []) {
          if (result.category === Category.ERROR) stats.errorCount++;
          if (result.category === Category.WARNING) stats.warningCount++;
          if (result.category === Category.INFO) stats.infoCount++;
          if (result.category === Category.SUCCESS) stats.successCount++;
        }
      }
    }
    this.reporting.timeEnd(Timing.CHECKS_LOAD, stats);
    this.reporting.reportInteraction(Interaction.CHECKS_STATS, stats);
  }

  override finalize() {
    document.removeEventListener('reload', this.reloadListener);
    document.removeEventListener(
      'visibilitychange',
      this.visibilityChangeListener
    );
    super.finalize();
  }

  // Must only be used by the checks service or whatever is in control of this
  // model.
  updateStateSetProvider(pluginName: string, patchset: ChecksPatchset) {
    const nextState = {...this.getState()};
    const pluginState = this.getPluginState(nextState, patchset);
    pluginState[pluginName] = {
      pluginName,
      loading: false,
      firstTimeLoad: true,
      runs: [],
      actions: [],
      links: [],
    };
    this.setState(nextState);
  }

  getPluginState(
    state: ChecksState,
    patchset: ChecksPatchset = ChecksPatchset.LATEST
  ) {
    if (patchset === ChecksPatchset.LATEST) {
      state.pluginStateLatest = {...state.pluginStateLatest};
      return state.pluginStateLatest;
    } else {
      state.pluginStateSelected = {...state.pluginStateSelected};
      return state.pluginStateSelected;
    }
  }

  updateStateSetLoading(pluginName: string, patchset: ChecksPatchset) {
    const nextState = {...this.getState()};
    const pluginState = this.getPluginState(nextState, patchset);
    pluginState[pluginName] = {
      ...pluginState[pluginName],
      loading: true,
    };
    this.setState(nextState);
  }

  updateStateSetError(
    pluginName: string,
    errorMessage: string,
    patchset: ChecksPatchset
  ) {
    const nextState = {...this.getState()};
    const pluginState = this.getPluginState(nextState, patchset);
    pluginState[pluginName] = {
      ...pluginState[pluginName],
      loading: false,
      firstTimeLoad: false,
      errorMessage,
      loginCallback: undefined,
      runs: [],
      actions: [],
    };
    this.setState(nextState);
  }

  updateStateSetNotLoggedIn(
    pluginName: string,
    loginCallback: () => void,
    patchset: ChecksPatchset
  ) {
    const nextState = {...this.getState()};
    const pluginState = this.getPluginState(nextState, patchset);
    pluginState[pluginName] = {
      ...pluginState[pluginName],
      loading: false,
      firstTimeLoad: false,
      errorMessage: undefined,
      loginCallback,
      runs: [],
      actions: [],
    };
    this.setState(nextState);
  }

  updateStateSetResults(
    pluginName: string,
    runs: CheckRunApi[],
    actions: Action[] = [],
    links: Link[] = [],
    summaryMessage: string | undefined,
    patchset: ChecksPatchset
  ) {
    // Protect against plugins not respecting required fields.
    runs = runs.filter(run => !!run.checkName && !!run.status);
    const attemptMap = createAttemptMap(runs);
    for (const attemptInfo of attemptMap.values()) {
      attemptInfo.attempts.sort(sortAttemptDetails);
    }
    const nextState = {...this.getState()};
    const pluginState = this.getPluginState(nextState, patchset);
    const oldState = pluginState[pluginName];
    pluginState[pluginName] = {
      ...oldState,
      loading: false,
      firstTimeLoad: oldState.loading ? false : oldState.firstTimeLoad,
      errorMessage: undefined,
      loginCallback: undefined,
      runs: runs.map(run => {
        const runId = `${run.checkName}-${run.change}-${run.patchset}-${run.attempt}`;
        const attemptInfo = attemptMap.get(run.checkName);
        assertIsDefined(attemptInfo, 'attemptInfo');
        return {
          ...run,
          attempt: run.attempt ?? 0,
          pluginName,
          internalRunId: runId,
          isLatestAttempt: attemptInfo.latestAttempt === (run.attempt ?? 0),
          isSingleAttempt: attemptInfo.isSingleAttempt,
          attemptDetails: attemptInfo.attempts,
          results: (run.results ?? []).map((result, i) => {
            return {
              ...result,
              internalResultId: `${runId}-${i}`,
            };
          }),
        };
      }),
      actions: [...actions],
      links: [...links],
      summaryMessage,
    };
    this.setState(nextState);
  }

  updateStateUpdateResult(
    pluginName: string,
    updatedRun: CheckRunApi,
    updatedResult: CheckResultApi,
    patchset: ChecksPatchset
  ) {
    const nextState = {...this.getState()};
    const pluginState = this.getPluginState(nextState, patchset);
    let runUpdated = false;
    const runs: CheckRun[] = pluginState[pluginName].runs.map(run => {
      if (run.change !== updatedRun.change) return run;
      if (run.patchset !== updatedRun.patchset) return run;
      if (run.attempt !== updatedRun.attempt) return run;
      if (run.checkName !== updatedRun.checkName) return run;
      let resultUpdated = false;
      const results: CheckResult[] = (run.results ?? []).map(result => {
        if (
          result.externalId &&
          result.externalId === updatedResult.externalId
        ) {
          runUpdated = true;
          resultUpdated = true;
          return {
            ...updatedResult,
            internalResultId: result.internalResultId,
          };
        }
        return result;
      });
      return resultUpdated ? {...run, results} : run;
    });
    if (!runUpdated) return;
    pluginState[pluginName] = {
      ...pluginState[pluginName],
      runs,
    };
    this.setState(nextState);
  }

  updateStateSetPatchset(num?: PatchSetNumber) {
    const newPatchset = num === this.latestPatchNum ? undefined : num;
    const oldPatchset = this.changeViewModel.getState()?.checksPatchset;
    // For `checksPatchset` itself we could just let updateState() do the
    // standard old===new comparison. But we have to make sure here that
    // the attempt reset only actually happens when a new patchset is chosen.
    if (newPatchset === oldPatchset) return;
    this.changeViewModel.updateState({
      checksPatchset: newPatchset,
      attempt: LATEST_ATTEMPT,
    });
  }

  updateStateSetAttempt(attemptNumberSelected: AttemptChoice) {
    this.changeViewModel.updateState({attempt: attemptNumberSelected});
  }

  updateStateSetRunFilter(runFilterRegexp: string) {
    this.changeViewModel.updateState({filter: runFilterRegexp});
  }

  reload(pluginName: string) {
    this.reloadSubjects[pluginName].next();
  }

  reloadAll() {
    for (const key of Object.keys(this.providers)) {
      this.reload(key);
    }
  }

  reloadForCheck(checkName?: string) {
    if (!checkName) return;
    const plugin = this.checkToPluginMap.get(checkName);
    if (plugin) this.reload(plugin);
  }

  updateResult(update: ChecksUpdate) {
    const {pluginName, run, result} = update;
    this.updateStateUpdateResult(
      pluginName,
      run,
      result,
      ChecksPatchset.LATEST
    );
    this.updateStateUpdateResult(
      pluginName,
      run,
      result,
      ChecksPatchset.SELECTED
    );
  }

  triggerAction(action: Action, run: CheckRun | undefined, context: string) {
    if (!action?.callback) return;
    if (!this.changeNum) return;
    const patchSet = run?.patchset ?? this.latestPatchNum;
    if (!patchSet) return;
    this.reporting.reportInteraction(Interaction.CHECKS_ACTION_TRIGGERED, {
      checkName: run?.checkName,
      actionName: action.name,
      context,
    });
    const promise = action.callback(
      this.changeNum,
      patchSet,
      run?.attempt,
      run?.externalId,
      run?.checkName,
      action.name
    );
    // If plugins return undefined or not a promise, then show no toast.
    if (!promise?.then) return;

    fireAlert(document, `Triggering action '${action.name}' ...`);
    from(promise)
      // If the action takes longer than 5 seconds, then most likely the
      // user is either not interested or the result not relevant anymore.
      .pipe(takeUntil(timer(5000)))
      .subscribe(result => {
        if (result.errorMessage || result.message) {
          fireAlert(document, `${result.message ?? result.errorMessage}`);
        } else {
          fireEvent(document, 'hide-alert');
        }
        if (result.shouldReload) {
          this.reloadForCheck(run?.checkName);
        }
      });
  }

  register(checksPlugin: ChecksPlugin) {
    const {pluginName, provider, config} = checksPlugin;
    if (this.providers[pluginName]) {
      console.warn(
        `Plugin '${pluginName}' was trying to register twice as a Checks UI provider. Ignored.`
      );
      return;
    }
    this.providers[pluginName] = provider;
    this.reloadSubjects[pluginName] = new BehaviorSubject<void>(undefined);
    this.updateStateSetProvider(pluginName, ChecksPatchset.LATEST);
    this.updateStateSetProvider(pluginName, ChecksPatchset.SELECTED);
    this.initFetchingOfData(pluginName, config, ChecksPatchset.LATEST);
    this.initFetchingOfData(pluginName, config, ChecksPatchset.SELECTED);
  }

  initFetchingOfData(
    pluginName: string,
    config: ChecksApiConfig,
    patchset: ChecksPatchset
  ) {
    const pollIntervalMs = (config?.fetchPollingIntervalSeconds ?? 60) * 1000;
    // Various events should trigger fetching checks from the provider:
    // 1. Change number and patchset number changes.
    // 2. Specific reload requests.
    // 3. Regular polling starting with an initial fetch right now.
    // 4. A hidden Gerrit tab becoming visible.
    this.subscriptions.push(
      combineLatest([
        this.changeModel.change$,
        patchset === ChecksPatchset.LATEST
          ? this.changeModel.latestPatchNum$
          : this.checksSelectedPatchsetNumber$,
        this.reloadSubjects[pluginName],
        pollIntervalMs === 0 ? from([0]) : timer(0, pollIntervalMs),
        this.documentVisibilityChange$,
      ])
        .pipe(
          takeWhile(_ => !!this.providers[pluginName]),
          filter(_ => document.visibilityState !== 'hidden'),
          throttleTime(500, undefined, {leading: true, trailing: true}),
          switchMap(([change, patchNum]): Observable<FetchResponse> => {
            if (!change || !patchNum) return of(this.empty());
            if (typeof patchNum !== 'number') return of(this.empty());
            assertIsDefined(change.revisions, 'change.revisions');
            const patchsetSha = getShaByPatchNum(change.revisions, patchNum);
            // Sometimes patchNum is updated earlier than change, so change
            // revisions don't have patchNum yet
            if (!patchsetSha) return of(this.empty());
            const data: ChangeData = {
              changeNumber: change?._number,
              patchsetNumber: patchNum,
              patchsetSha,
              repo: change.project,
              commitMessage: getCurrentRevision(change)?.commit?.message,
              changeInfo: change as ChangeInfo,
            };
            return this.fetchResults(pluginName, data, patchset);
          }),
          catchError(e => {
            // This should not happen and is really severe, because it means that
            // the Observable has terminated and we won't recover from that. No
            // further attempts to fetch results for this plugin will be made.
            this.reporting.error(`checks-model crash for ${pluginName}`, e);
            return of(this.createErrorResponse(pluginName, e));
          })
        )
        .subscribe(response => {
          switch (response.responseCode) {
            case ResponseCode.ERROR: {
              const message = response.errorMessage ?? '-';
              this.reporting.reportExecution(Execution.CHECKS_API_ERROR, {
                plugin: pluginName,
                message,
              });
              this.updateStateSetError(pluginName, message, patchset);
              break;
            }
            case ResponseCode.NOT_LOGGED_IN: {
              assertIsDefined(response.loginCallback, 'loginCallback');
              this.reporting.reportExecution(
                Execution.CHECKS_API_NOT_LOGGED_IN,
                {
                  plugin: pluginName,
                }
              );
              this.updateStateSetNotLoggedIn(
                pluginName,
                response.loginCallback,
                patchset
              );
              break;
            }
            case ResponseCode.OK: {
              this.updateStateSetResults(
                pluginName,
                response.runs ?? [],
                response.actions ?? [],
                response.links ?? [],
                response.summaryMessage,
                patchset
              );
              break;
            }
          }
        })
    );
  }

  private empty(): FetchResponse {
    return {
      responseCode: ResponseCode.OK,
      runs: [],
    };
  }

  private createErrorResponse(pluginName: string, error: Error): FetchResponse {
    return {
      responseCode: ResponseCode.ERROR,
      errorMessage:
        `Error message from plugin '${pluginName}':` +
        ` ${JSON.stringify(error)}`,
    };
  }

  private fetchResults(
    pluginName: string,
    data: ChangeData,
    patchset: ChecksPatchset
  ): Observable<FetchResponse> {
    this.updateStateSetLoading(pluginName, patchset);
    const timer = this.reporting.getTimer('ChecksPluginFetch');
    const fetchPromise = this.providers[pluginName]
      .fetch(data)
      .then(response => {
        timer.end({pluginName});
        return response;
      });

    return from(fetchPromise)
      .pipe(timeout(FETCH_RESULT_TIMEOUT_MS))
      .pipe(catchError(e => of(this.createErrorResponse(pluginName, e))));
  }
}
