/**
 * @license
 * Copyright (C) 2016 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.
 */
import {AppContext} from '../app-context';
import {FlagsService} from '../flags/flags';
import {EventValue, ReportingService, Timer} from './gr-reporting';
import {hasOwnProperty} from '../../utils/common-util';
import {NumericChangeId} from '../../types/common';
import {EventDetails} from '../../api/reporting';

// Latency reporting constants.

const TIMING = {
  TYPE: 'timing-report',
  CATEGORY: {
    UI_LATENCY: 'UI Latency',
    RPC: 'RPC Timing',
  },
  EVENT: {
    APP_STARTED: 'App Started',
  },
};

const LIFECYCLE = {
  TYPE: 'lifecycle',
  CATEGORY: {
    DEFAULT: 'Default',
    EXTENSION_DETECTED: 'Extension detected',
    PLUGINS_INSTALLED: 'Plugins installed',
    VISIBILITY: 'Visibility',
    EXECUTION: 'Execution',
  },
};

const INTERACTION = {
  TYPE: 'interaction',
  CATEGORY: {
    DEFAULT: 'Default',
    VISIBILITY: 'Visibility',
  },
};

const NAVIGATION = {
  TYPE: 'nav-report',
  CATEGORY: {
    LOCATION_CHANGED: 'Location Changed',
  },
  EVENT: {
    PAGE: 'Page',
  },
};

const ERROR = {
  TYPE: 'error',
  CATEGORY: {
    EXCEPTION: 'exception',
    ERROR_DIALOG: 'Error Dialog',
  },
};

const TIMER = {
  CHANGE_DISPLAYED: 'ChangeDisplayed',
  CHANGE_LOAD_FULL: 'ChangeFullyLoaded',
  DASHBOARD_DISPLAYED: 'DashboardDisplayed',
  DIFF_VIEW_CONTENT_DISPLAYED: 'DiffViewOnlyContent',
  DIFF_VIEW_DISPLAYED: 'DiffViewDisplayed',
  DIFF_VIEW_LOAD_FULL: 'DiffViewFullyLoaded',
  FILE_LIST_DISPLAYED: 'FileListDisplayed',
  PLUGINS_LOADED: 'PluginsLoaded',
  STARTUP_CHANGE_DISPLAYED: 'StartupChangeDisplayed',
  STARTUP_CHANGE_LOAD_FULL: 'StartupChangeFullyLoaded',
  STARTUP_DASHBOARD_DISPLAYED: 'StartupDashboardDisplayed',
  STARTUP_DIFF_VIEW_CONTENT_DISPLAYED: 'StartupDiffViewOnlyContent',
  STARTUP_DIFF_VIEW_DISPLAYED: 'StartupDiffViewDisplayed',
  STARTUP_DIFF_VIEW_LOAD_FULL: 'StartupDiffViewFullyLoaded',
  STARTUP_FILE_LIST_DISPLAYED: 'StartupFileListDisplayed',
  WEB_COMPONENTS_READY: 'WebComponentsReady',
  METRICS_PLUGIN_LOADED: 'MetricsPluginLoaded',
};

const STARTUP_TIMERS = {
  [TIMER.PLUGINS_LOADED]: 0,
  [TIMER.METRICS_PLUGIN_LOADED]: 0,
  [TIMER.STARTUP_CHANGE_DISPLAYED]: 0,
  [TIMER.STARTUP_CHANGE_LOAD_FULL]: 0,
  [TIMER.STARTUP_DASHBOARD_DISPLAYED]: 0,
  [TIMER.STARTUP_DIFF_VIEW_CONTENT_DISPLAYED]: 0,
  [TIMER.STARTUP_DIFF_VIEW_DISPLAYED]: 0,
  [TIMER.STARTUP_DIFF_VIEW_LOAD_FULL]: 0,
  [TIMER.STARTUP_FILE_LIST_DISPLAYED]: 0,
  [TIMING.EVENT.APP_STARTED]: 0,
  // WebComponentsReady timer is triggered from gr-router.
  [TIMER.WEB_COMPONENTS_READY]: 0,
};

const DRAFT_ACTION_TIMER = 'TimeBetweenDraftActions';
const DRAFT_ACTION_TIMER_MAX = 2 * 60 * 1000; // 2 minutes.
const SLOW_RPC_THRESHOLD = 500;

export function initErrorReporter(appContext: AppContext) {
  const reportingService = appContext.reportingService;

  const normalizeError = (err: Error | unknown) => {
    if (err instanceof Error) {
      return err;
    }
    let msg = '';
    if (typeof err === 'string') {
      msg += err;
    } else {
      msg += JSON.stringify(err);
    }
    const error = new Error(msg);
    error.stack = 'unknown';
    return error;
  };
  // TODO(dmfilippov): TS-fix-any oldOnError - define correct type
  const onError = function (
    oldOnError: Function,
    msg: Event | string,
    url?: string,
    line?: number,
    column?: number,
    error?: Error
  ) {
    if (oldOnError) {
      oldOnError(msg, url, line, column, error);
    }
    if (error) {
      line = line ?? error.lineNumber;
      column = column ?? error.columnNumber;
    }
    reportingService.error(normalizeError(error), 'onError', {
      line,
      column,
      url,
      msg,
    });
    return true;
  };
  // TODO(dmfilippov): TS-fix-any unclear what is context
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const catchErrors = function (opt_context?: any) {
    const context = opt_context || window;
    const oldOnError = context.onerror;
    context.onerror = (
      event: Event | string,
      source?: string,
      lineno?: number,
      colno?: number,
      error?: Error
    ) => {
      return onError(oldOnError, event, source, lineno, colno, error);
    };
    context.addEventListener(
      'unhandledrejection',
      (e: PromiseRejectionEvent) => {
        reportingService.error(normalizeError(e.reason), 'unhandledrejection');
      }
    );
  };

  catchErrors();

  // for testing
  return {catchErrors};
}

export function initPerformanceReporter(appContext: AppContext) {
  const reportingService = appContext.reportingService;
  // PerformanceObserver interface is a browser API.
  if (window.PerformanceObserver) {
    const supportedEntryTypes = PerformanceObserver.supportedEntryTypes || [];
    // Safari doesn't support longtask yet
    if (supportedEntryTypes.includes('longtask')) {
      const catchLongJsTasks = new PerformanceObserver(list => {
        for (const task of list.getEntries()) {
          // We are interested in longtask longer than 200 ms (default is 50 ms)
          if (task.duration > 200) {
            reportingService.reporter(
              TIMING.TYPE,
              TIMING.CATEGORY.UI_LATENCY,
              `Task ${task.name}`,
              Math.round(task.duration),
              {},
              false
            );
          }
        }
      });
      catchLongJsTasks.observe({entryTypes: ['longtask']});
    }
  }
}

export function initVisibilityReporter(appContext: AppContext) {
  const reportingService = appContext.reportingService;
  document.addEventListener('visibilitychange', () => {
    reportingService.onVisibilityChange();
  });
}

// Calculates the time of Gerrit being in a background tab. When Gerrit reports
// a pageLoad metric it’s attached to its details for latency analysis.
// It resets on locationChange.
class HiddenDurationTimer {
  public accHiddenDurationMs = 0;

  public lastVisibleTimestampMs: number | null = null;

  constructor() {
    this.reset();
  }

  reset() {
    this.accHiddenDurationMs = 0;
    this.lastVisibleTimestampMs = 0;
  }

  onVisibilityChange() {
    if (document.visibilityState === 'hidden') {
      this.lastVisibleTimestampMs = now();
    } else if (document.visibilityState === 'visible') {
      if (this.lastVisibleTimestampMs !== null) {
        this.accHiddenDurationMs += now() - this.lastVisibleTimestampMs;
        // Set to null for guarding against two 'visible' events in a row.
        this.lastVisibleTimestampMs = null;
      }
    }
  }

  get hiddenDurationMs() {
    if (
      document.visibilityState === 'hidden' &&
      this.lastVisibleTimestampMs !== null
    ) {
      return this.accHiddenDurationMs + now() - this.lastVisibleTimestampMs;
    }
    return this.accHiddenDurationMs;
  }
}

export function now() {
  return Math.round(window.performance.now());
}

type PeformanceTimingEventName = keyof Omit<PerformanceTiming, 'toJSON'>;

interface EventInfo {
  type: string;
  category: string;
  name: string;
  value?: EventValue;
  eventStart: number;
  eventDetails?: string;
  repoName?: string;
  changeId?: string;
  inBackgroundTab?: boolean;
  enabledExperiments?: string;
}

interface PageLoadDetails {
  rpcList: SlowRpcCall[];
  hiddenDurationMs: number;
  screenSize?: {width: number; height: number};
  viewport?: {width: number; height: number};
  usedJSHeapSizeMb?: number;
}

interface SlowRpcCall {
  anonymizedUrl: string;
  elapsed: number;
}

type PendingReportInfo = [EventInfo, boolean | undefined];

export class GrReporting implements ReportingService {
  private readonly _flagsService: FlagsService;

  private readonly _baselines = STARTUP_TIMERS;

  private reportRepoName: string | undefined;

  private reportChangeId: NumericChangeId | undefined;

  private timers: {timeBetweenDraftActions: Timer | null} = {
    timeBetweenDraftActions: null,
  };

  private pending: PendingReportInfo[] = [];

  private slowRpcList: SlowRpcCall[] = [];

  /**
   * Keeps track of which ids were already reported to have been executed.
   * Execution ids should only be reported once per session.
   */
  private executionReported = new Set<string>();

  public readonly hiddenDurationTimer = new HiddenDurationTimer();

  constructor(flagsService: FlagsService) {
    this._flagsService = flagsService;
  }

  private get performanceTiming() {
    return window.performance.timing;
  }

  private get slowRpcSnapshot() {
    return (this.slowRpcList || []).slice();
  }

  private _arePluginsLoaded() {
    return (
      this._baselines && !hasOwnProperty(this._baselines, TIMER.PLUGINS_LOADED)
    );
  }

  private _isMetricsPluginLoaded() {
    return (
      this._arePluginsLoaded() ||
      (this._baselines &&
        !hasOwnProperty(this._baselines, TIMER.METRICS_PLUGIN_LOADED))
    );
  }

  /**
   * Reporter reports events. Events will be queued if metrics plugin is not
   * yet installed.
   *
   * @param noLog If true, the event will not be logged to the JS console.
   */
  reporter(
    type: string,
    category: string,
    eventName: string,
    eventValue?: EventValue,
    eventDetails?: EventDetails,
    noLog?: boolean
  ) {
    const eventInfo = this._createEventInfo(
      type,
      category,
      eventName,
      eventValue,
      eventDetails
    );
    if (type === ERROR.TYPE && category === ERROR.CATEGORY.EXCEPTION) {
      console.error(
        (typeof eventValue === 'object' && eventValue.error) || eventName
      );
    }

    // We report events immediately when metrics plugin is loaded
    if (this._isMetricsPluginLoaded() && !this.pending.length) {
      this._reportEvent(eventInfo, noLog);
    } else {
      // We cache until metrics plugin is loaded
      this.pending.push([eventInfo, noLog]);
      if (this._isMetricsPluginLoaded()) {
        this.pending.forEach(([eventInfo, opt_noLog]) => {
          this._reportEvent(eventInfo, opt_noLog);
        });
        this.pending = [];
      }
    }
  }

  private _reportEvent(eventInfo: EventInfo, opt_noLog?: boolean) {
    const {type, value, name} = eventInfo;
    document.dispatchEvent(new CustomEvent(type, {detail: eventInfo}));
    if (opt_noLog) {
      return;
    }
    if (type !== ERROR.TYPE) {
      if (value !== undefined) {
        console.info(`Reporting: ${name}: ${value}`);
      } else {
        console.info(`Reporting: ${name}`);
      }
    }
  }

  private _createEventInfo(
    type: string,
    category: string,
    name: string,
    value?: EventValue,
    eventDetails?: EventDetails
  ): EventInfo {
    const eventInfo: EventInfo = {
      type,
      category,
      name,
      value,
      eventStart: now(),
    };

    if (
      typeof eventDetails === 'object' &&
      Object.entries(eventDetails).length !== 0
    ) {
      eventInfo.eventDetails = JSON.stringify(eventDetails);
    }

    if (this.reportRepoName) {
      eventInfo.repoName = this.reportRepoName;
    }
    if (this.reportChangeId) {
      eventInfo.changeId = `${this.reportChangeId}`;
    }

    const isInBackgroundTab = document.visibilityState === 'hidden';
    if (isInBackgroundTab !== undefined) {
      eventInfo.inBackgroundTab = isInBackgroundTab;
    }

    if (this._flagsService.enabledExperiments.length) {
      eventInfo.enabledExperiments = JSON.stringify(
        this._flagsService.enabledExperiments
      );
    }

    return eventInfo;
  }

  /**
   * User-perceived app start time, should be reported when the app is ready.
   */
  appStarted() {
    this.timeEnd(TIMING.EVENT.APP_STARTED);
    this._reportNavResTimes();
  }

  onVisibilityChange() {
    this.hiddenDurationTimer.onVisibilityChange();
    const eventName = `Visibility changed to ${document.visibilityState}`;
    this.reporter(
      LIFECYCLE.TYPE,
      LIFECYCLE.CATEGORY.VISIBILITY,
      eventName,
      undefined,
      {
        hiddenDurationMs: this.hiddenDurationTimer.hiddenDurationMs,
      },
      true
    );
  }

  /**
   * Browser's navigation and resource timings
   */
  private _reportNavResTimes() {
    const perfEvents = Object.keys(this.performanceTiming.toJSON());
    perfEvents.forEach(eventName =>
      this._reportPerformanceTiming(eventName as PeformanceTimingEventName)
    );
  }

  private _reportPerformanceTiming(
    eventName: PeformanceTimingEventName,
    eventDetails?: EventDetails
  ) {
    const eventTiming = this.performanceTiming[eventName];
    if (eventTiming > 0) {
      const elapsedTime = eventTiming - this.performanceTiming.navigationStart;
      // NavResTime - Navigation and resource timings.
      this.reporter(
        TIMING.TYPE,
        TIMING.CATEGORY.UI_LATENCY,
        `NavResTime - ${eventName}`,
        elapsedTime,
        eventDetails,
        true
      );
    }
  }

  beforeLocationChanged() {
    for (const prop of Object.keys(this._baselines)) {
      delete this._baselines[prop];
    }
    this.time(TIMER.CHANGE_DISPLAYED);
    this.time(TIMER.CHANGE_LOAD_FULL);
    this.time(TIMER.DASHBOARD_DISPLAYED);
    this.time(TIMER.DIFF_VIEW_CONTENT_DISPLAYED);
    this.time(TIMER.DIFF_VIEW_DISPLAYED);
    this.time(TIMER.DIFF_VIEW_LOAD_FULL);
    this.time(TIMER.FILE_LIST_DISPLAYED);
    this.reportRepoName = undefined;
    this.reportChangeId = undefined;
    // reset slow rpc list since here start page loads which report these rpcs
    this.slowRpcList = [];
    this.hiddenDurationTimer.reset();
  }

  locationChanged(page: string) {
    this.reporter(
      NAVIGATION.TYPE,
      NAVIGATION.CATEGORY.LOCATION_CHANGED,
      NAVIGATION.EVENT.PAGE,
      page
    );
  }

  dashboardDisplayed() {
    if (hasOwnProperty(this._baselines, TIMER.STARTUP_DASHBOARD_DISPLAYED)) {
      this.timeEnd(TIMER.STARTUP_DASHBOARD_DISPLAYED, this._pageLoadDetails());
    } else {
      this.timeEnd(TIMER.DASHBOARD_DISPLAYED, this._pageLoadDetails());
    }
  }

  changeDisplayed() {
    if (hasOwnProperty(this._baselines, TIMER.STARTUP_CHANGE_DISPLAYED)) {
      this.timeEnd(TIMER.STARTUP_CHANGE_DISPLAYED, this._pageLoadDetails());
    } else {
      this.timeEnd(TIMER.CHANGE_DISPLAYED, this._pageLoadDetails());
    }
  }

  changeFullyLoaded() {
    if (hasOwnProperty(this._baselines, TIMER.STARTUP_CHANGE_LOAD_FULL)) {
      this.timeEnd(TIMER.STARTUP_CHANGE_LOAD_FULL);
    } else {
      this.timeEnd(TIMER.CHANGE_LOAD_FULL);
    }
  }

  diffViewDisplayed() {
    if (hasOwnProperty(this._baselines, TIMER.STARTUP_DIFF_VIEW_DISPLAYED)) {
      this.timeEnd(TIMER.STARTUP_DIFF_VIEW_DISPLAYED, this._pageLoadDetails());
    } else {
      this.timeEnd(TIMER.DIFF_VIEW_DISPLAYED, this._pageLoadDetails());
    }
  }

  diffViewFullyLoaded() {
    if (hasOwnProperty(this._baselines, TIMER.STARTUP_DIFF_VIEW_LOAD_FULL)) {
      this.timeEnd(TIMER.STARTUP_DIFF_VIEW_LOAD_FULL);
    } else {
      this.timeEnd(TIMER.DIFF_VIEW_LOAD_FULL);
    }
  }

  diffViewContentDisplayed() {
    if (
      hasOwnProperty(this._baselines, TIMER.STARTUP_DIFF_VIEW_CONTENT_DISPLAYED)
    ) {
      this.timeEnd(TIMER.STARTUP_DIFF_VIEW_CONTENT_DISPLAYED);
    } else {
      this.timeEnd(TIMER.DIFF_VIEW_CONTENT_DISPLAYED);
    }
  }

  fileListDisplayed() {
    if (hasOwnProperty(this._baselines, TIMER.STARTUP_FILE_LIST_DISPLAYED)) {
      this.timeEnd(TIMER.STARTUP_FILE_LIST_DISPLAYED);
    } else {
      this.timeEnd(TIMER.FILE_LIST_DISPLAYED);
    }
  }

  private _pageLoadDetails(): PageLoadDetails {
    const details: PageLoadDetails = {
      rpcList: this.slowRpcSnapshot,
      hiddenDurationMs: this.hiddenDurationTimer.accHiddenDurationMs,
    };

    if (window.screen) {
      details.screenSize = {
        width: window.screen.width,
        height: window.screen.height,
      };
    }

    if (document?.documentElement) {
      details.viewport = {
        width: document.documentElement.clientWidth,
        height: document.documentElement.clientHeight,
      };
    }

    if (window.performance?.memory) {
      const toMb = (bytes: number) =>
        Math.round((bytes / (1024 * 1024)) * 100) / 100;
      details.usedJSHeapSizeMb = toMb(window.performance.memory.usedJSHeapSize);
    }

    details.hiddenDurationMs = this.hiddenDurationTimer.hiddenDurationMs;
    return details;
  }

  reportExtension(name: string) {
    this.reporter(LIFECYCLE.TYPE, LIFECYCLE.CATEGORY.EXTENSION_DETECTED, name);
  }

  pluginLoaded(name: string) {
    if (name.startsWith('metrics-')) {
      this.timeEnd(TIMER.METRICS_PLUGIN_LOADED);
    }
  }

  pluginsLoaded(pluginsList?: string[]) {
    this.timeEnd(TIMER.PLUGINS_LOADED);
    this.reporter(
      LIFECYCLE.TYPE,
      LIFECYCLE.CATEGORY.PLUGINS_INSTALLED,
      LIFECYCLE.CATEGORY.PLUGINS_INSTALLED,
      undefined,
      {pluginsList: pluginsList || []},
      true
    );
  }

  /**
   * Reset named timer.
   */
  time(name: string) {
    this._baselines[name] = now();
    window.performance.mark(`${name}-start`);
  }

  /**
   * Finish named timer and report it to server.
   */
  timeEnd(name: string, eventDetails?: EventDetails) {
    if (!hasOwnProperty(this._baselines, name)) {
      return;
    }
    const baseTime = this._baselines[name];
    delete this._baselines[name];
    this._reportTiming(name, now() - baseTime, eventDetails);

    // Finalize the interval. Either from a registered start mark or
    // the navigation start time (if baseTime is 0).
    if (baseTime !== 0) {
      window.performance.measure(name, `${name}-start`);
    } else {
      // Microsoft Edge does not handle the 2nd param correctly
      // (if undefined).
      window.performance.measure(name);
    }
  }

  /**
   * Reports just line timeEnd, but additionally reports an average given a
   * denominator and a separate reporting name for the average.
   *
   * @param name Timing name.
   * @param averageName Average timing name.
   * @param denominator Number by which to divide the total to
   *     compute the average.
   */
  timeEndWithAverage(name: string, averageName: string, denominator: number) {
    if (!hasOwnProperty(this._baselines, name)) {
      return;
    }
    const baseTime = this._baselines[name];
    this.timeEnd(name);

    // Guard against division by zero.
    if (!denominator) {
      return;
    }
    const time = now() - baseTime;
    this._reportTiming(averageName, time / denominator);
  }

  /**
   * Send a timing report with an arbitrary time value.
   *
   * @param name Timing name.
   * @param time The time to report as an integer of milliseconds.
   * @param eventDetails non sensitive details
   */
  private _reportTiming(
    name: string,
    time: number,
    eventDetails?: EventDetails
  ) {
    this.reporter(
      TIMING.TYPE,
      TIMING.CATEGORY.UI_LATENCY,
      name,
      time,
      eventDetails
    );
  }

  /**
   * Get a timer object to for reporting a user timing. The start time will be
   * the time that the object has been created, and the end time will be the
   * time that the "end" method is called on the object.
   */
  getTimer(name: string): Timer {
    let called = false;
    let start: number;
    let max: number | null = null;

    const timer: Timer = {
      // Clear the timer and reset the start time.
      reset: () => {
        called = false;
        start = now();
        return timer;
      },

      // Stop the timer and report the intervening time.
      end: () => {
        if (called) {
          throw new Error(`Timer for "${name}" already ended.`);
        }
        called = true;
        const time = now() - start;

        // If a maximum is specified and the time exceeds it, do not report.
        if (max && time > max) {
          return timer;
        }

        this._reportTiming(name, time);
        return timer;
      },

      // Set a maximum reportable time. If a maximum is set and the timer is
      // ended after the specified amount of time, the value is not reported.
      withMaximum(maximum) {
        max = maximum;
        return timer;
      },
    };

    // The timer is initialized to its creation time.
    return timer.reset();
  }

  /**
   * Log timing information for an RPC.
   *
   * @param anonymizedUrl The URL of the RPC with tokens obfuscated.
   * @param elapsed The time elapsed of the RPC.
   */
  reportRpcTiming(anonymizedUrl: string, elapsed: number) {
    this.reporter(
      TIMING.TYPE,
      TIMING.CATEGORY.RPC,
      'RPC-' + anonymizedUrl,
      elapsed,
      {},
      true
    );
    if (elapsed >= SLOW_RPC_THRESHOLD) {
      this.slowRpcList.push({anonymizedUrl, elapsed});
    }
  }

  reportLifeCycle(eventName: string, details: EventDetails) {
    this.reporter(
      LIFECYCLE.TYPE,
      LIFECYCLE.CATEGORY.DEFAULT,
      eventName,
      undefined,
      details,
      true
    );
  }

  reportInteraction(eventName: string, details: EventDetails) {
    this.reporter(
      INTERACTION.TYPE,
      INTERACTION.CATEGORY.DEFAULT,
      eventName,
      undefined,
      details,
      true
    );
  }

  reportExecution(id: string, details: EventDetails) {
    if (this.executionReported.has(id)) return;
    this.executionReported.add(id);
    this.reporter(
      LIFECYCLE.TYPE,
      LIFECYCLE.CATEGORY.EXECUTION,
      id,
      undefined,
      details,
      false
    );
  }

  /**
   * A draft interaction was started. Update the time-between-draft-actions
   * timer.
   */
  recordDraftInteraction() {
    // If there is no timer defined, then this is the first interaction.
    // Set up the timer so that it's ready to record the intervening time when
    // called again.
    const timer = this.timers.timeBetweenDraftActions;
    if (!timer) {
      // Create a timer with a maximum length.
      this.timers.timeBetweenDraftActions = this.getTimer(
        DRAFT_ACTION_TIMER
      ).withMaximum(DRAFT_ACTION_TIMER_MAX);
      return;
    }

    // Mark the time and reinitialize the timer.
    timer.end().reset();
  }

  error(error: Error, errorSource?: string, details?: EventDetails) {
    const eventDetails = details ?? {};
    const message = `${errorSource ? errorSource + ': ' : ''}${error.message}`;

    this.reporter(
      ERROR.TYPE,
      ERROR.CATEGORY.EXCEPTION,
      message,
      {error},
      {...eventDetails, stack: error.stack}
    );
  }

  reportErrorDialog(message: string) {
    this.reporter(
      ERROR.TYPE,
      ERROR.CATEGORY.ERROR_DIALOG,
      'ErrorDialog: ' + message,
      {error: new Error(message)}
    );
  }

  setRepoName(repoName: string) {
    this.reportRepoName = repoName;
  }

  setChangeId(changeId: NumericChangeId) {
    this.reportChangeId = changeId;
  }
}

export const DEFAULT_STARTUP_TIMERS = {...STARTUP_TIMERS};
