// Copyright (C) 2022 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 {
  showAllowUSBDebugging,
  showConnectionLostError,
  showExtensionNotInstalled,
  showFailedToPushBinary,
  showIssueParsingTheTracedResponse,
  showNoDeviceSelected,
  showWebsocketConnectionIssue,
  showWebUSBErrorV2,
} from '../../frontend/error_dialog';
import {getErrorMessage} from '../errors';

import {OnMessageCallback} from './recording_interfaces_v2';
import {
  ALLOW_USB_DEBUGGING,
  BINARY_PUSH_FAILURE,
  BINARY_PUSH_UNKNOWN_RESPONSE,
  EXTENSION_NOT_INSTALLED,
  NO_DEVICE_SELECTED,
  PARSING_UNABLE_TO_DECODE_METHOD,
  PARSING_UNKNWON_REQUEST_ID,
  PARSING_UNRECOGNIZED_MESSAGE,
  PARSING_UNRECOGNIZED_PORT,
  WEBSOCKET_UNABLE_TO_CONNECT,
} from './recording_utils';


// The pattern for handling recording error can have the following nesting in
// case of errors:
// A. wrapRecordingError -> wraps a promise
// B. onFailure -> has user defined logic and calls showRecordingModal
// C. showRecordingModal -> shows UX for a given error; this is not called
//    directly by wrapRecordingError, because we want the caller (such as the
//    UI) to dictate the UX

// This method takes a promise and a callback to be execute in case the promise
// fails. It then awaits the promise and executes the callback in case of
// failure. In the recording code it is used to wrap:
// 1. Acessing the WebUSB API.
// 2. Methods returning promises which can be rejected. For instance:
// a) When the user clicks 'Add a new device' but then doesn't select a valid
//    device.
// b) When the user starts a tracing session, but cancels it before they
//    authorize the session on the device.
export async function wrapRecordingError<T>(
    promise: Promise<T>, onFailure: OnMessageCallback): Promise<T|undefined> {
  try {
    return await promise;
  } catch (e) {
    // Sometimes the message is wrapped in an Error object, sometimes not, so
    // we make sure we transform it into a string.
    const errorMessage = getErrorMessage(e);
    onFailure(errorMessage);
    return undefined;
  }
}

// Shows a modal for every known type of error which can arise during recording.
// In this way, errors occuring at different levels of the recording process
// can be handled in a central location.
export function showRecordingModal(message: string): void {
  if ([
        'Unable to claim interface.',
        'The specified endpoint is not part of a claimed and selected ' +
            'alternate interface.',
        // thrown when calling the 'reset' method on a WebUSB device.
        'Unable to reset the device.',
      ].some((partOfMessage) => message.includes(partOfMessage))) {
    showWebUSBErrorV2();
  } else if (
      [
        'A transfer error has occurred.',
        'The device was disconnected.',
        'The transfer was cancelled.',
      ].some((partOfMessage) => message.includes(partOfMessage)) ||
      isDeviceDisconnectedError(message)) {
    showConnectionLostError();
  } else if (message === ALLOW_USB_DEBUGGING) {
    showAllowUSBDebugging();
  } else if (isMessageComposedOf(
                 message,
                 [BINARY_PUSH_FAILURE, BINARY_PUSH_UNKNOWN_RESPONSE])) {
    showFailedToPushBinary(message.substring(message.indexOf(':') + 1));
  } else if (message === NO_DEVICE_SELECTED) {
    showNoDeviceSelected();
  } else if (WEBSOCKET_UNABLE_TO_CONNECT === message) {
    showWebsocketConnectionIssue(message);
  } else if (message === EXTENSION_NOT_INSTALLED) {
    showExtensionNotInstalled();
  } else if (isMessageComposedOf(message, [
               PARSING_UNKNWON_REQUEST_ID,
               PARSING_UNABLE_TO_DECODE_METHOD,
               PARSING_UNRECOGNIZED_PORT,
               PARSING_UNRECOGNIZED_MESSAGE,
             ])) {
    showIssueParsingTheTracedResponse(message);
  } else {
    throw new Error(`${message}`);
  }
}

function isDeviceDisconnectedError(message: string) {
  return message.includes('Device with serial') &&
      message.includes('was disconnected.');
}

function isMessageComposedOf(message: string, issues: string[]) {
  for (const issue of issues) {
    if (message.includes(issue)) {
      return true;
    }
  }
  return false;
}

// Exception thrown by the Recording logic.
export class RecordingError extends Error {}
