text: /**
   * Copyright (c) Facebook, Inc. and its affiliates.
   *
   * This source code is licensed under the MIT license found in the
   * LICENSE file in the root directory of this source tree.
   *
   * @flow
   * @format
   */
  
  'use strict';
  
  import * as LogBoxSymbolication from './LogBoxSymbolication';
  
  import type {Category, Message, ComponentStack} from './parseLogBoxLog';
  import type {Stack} from './LogBoxSymbolication';
  
  export type SymbolicationRequest = $ReadOnly<{|
    abort: () => void,
  |}>;
  
  class LogBoxLog {
    message: Message;
    category: Category;
    componentStack: ComponentStack;
    stack: Stack;
    count: number;
    symbolicated:
      | $ReadOnly<{|error: null, stack: null, status: 'NONE'|}>
      | $ReadOnly<{|error: null, stack: null, status: 'PENDING'|}>
      | $ReadOnly<{|error: null, stack: Stack, status: 'COMPLETE'|}>
      | $ReadOnly<{|error: Error, stack: null, status: 'FAILED'|}> = {
      error: null,
      stack: null,
      status: 'NONE',
    };
  
    constructor(
      message: Message,
      stack: Stack,
      category: string,
      componentStack: ComponentStack,
    ) {
      this.message = message;
      this.stack = stack;
      this.category = category;
      this.componentStack = componentStack;
      this.count = 1;
    }
  
    incrementCount(): void {
      this.count += 1;
    }
  
    getAvailableStack(): Stack {
      return this.symbolicated.status === 'COMPLETE'
        ? this.symbolicated.stack
        : this.stack;
    }
  
    retrySymbolicate(callback: () => void): SymbolicationRequest {
      LogBoxSymbolication.deleteStack(this.stack);
      return this.symbolicate(callback);
    }
  
    symbolicate(callback: () => void): SymbolicationRequest {
      let aborted = false;
  
      if (this.symbolicated.status !== 'COMPLETE') {
        const updateStatus = (error: ?Error, stack: ?Stack): void => {
          if (error != null) {
            this.symbolicated = {error, stack: null, status: 'FAILED'};
          } else if (stack != null) {
            this.symbolicated = {error: null, stack, status: 'COMPLETE'};
          } else {
            this.symbolicated = {error: null, stack: null, status: 'PENDING'};
          }
          if (!aborted) {
            callback();
          }
        };
  
        updateStatus(null, null);
        LogBoxSymbolication.symbolicate(this.stack).then(
          stack => {
            updateStatus(null, stack);
          },
          error => {
            updateStatus(error, null);
          },
        );
      }
  
      return {
        abort(): void {
          aborted = true;
        },
      };
    }
  }
  
  export default LogBoxLog;
  