// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

import type { ReactNode, MouseEvent, KeyboardEvent } from 'react';
import { PureComponent } from 'react';

import type { LocalizerType } from '../../types/Util.std.ts';
import * as Errors from '../../types/errors.std.ts';
import { createLogger } from '../../logging/log.std.ts';

const log = createLogger('ErrorBoundary');

export type Props = {
  i18n: LocalizerType;
  children: ReactNode;

  showDebugLog: () => void;
};

export type State = {
  error?: Error;
};

const CSS_MODULE = 'module-error-boundary-notification';

export class ErrorBoundary extends PureComponent<Props, State> {
  constructor(props: Props) {
    super(props);

    this.state = { error: undefined };
  }

  public static getDerivedStateFromError(error: Error): State {
    log.error('captured rendering error', Errors.toLogFormat(error));
    return { error };
  }

  public override render(): ReactNode {
    const { error } = this.state;
    const { i18n, children } = this.props;

    if (!error) {
      return children;
    }

    return (
      <div
        className={CSS_MODULE}
        onClick={this.#onClick.bind(this)}
        onKeyDown={this.#onKeyDown.bind(this)}
        role="button"
        tabIndex={0}
      >
        <div className={`${CSS_MODULE}__icon-container`}>
          <div className={`${CSS_MODULE}__icon`} />
        </div>
        <div className={`${CSS_MODULE}__message`}>
          {i18n('icu:ErrorBoundaryNotification__text')}
        </div>
      </div>
    );
  }

  #onClick(event: MouseEvent): void {
    event.stopPropagation();
    event.preventDefault();

    this.#onAction();
  }

  #onKeyDown(event: KeyboardEvent): void {
    if (event.key !== 'Enter' && event.key !== ' ') {
      return;
    }
    event.stopPropagation();
    event.preventDefault();

    this.#onAction();
  }

  #onAction(): void {
    const { showDebugLog } = this.props;
    showDebugLog();
  }
}
