// Copyright (C) 2019 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 {exists} from '../base/utils';
import {isAdbTarget} from '../common/state';
import {
  extractDurationFromTraceConfig,
  extractTraceConfig,
} from '../core/trace_config_utils';
import {globals} from '../frontend/globals';

import {Adb} from './adb_interfaces';
import {ReadBuffersResponse} from './consumer_port_types';
import {Consumer, RpcConsumerPort} from './record_controller_interfaces';

export enum AdbConnectionState {
  READY_TO_CONNECT,
  AUTH_IN_PROGRESS,
  CONNECTED,
  CLOSED,
}

interface Command {
  method: string;
  params: Uint8Array;
}

export abstract class AdbBaseConsumerPort extends RpcConsumerPort {
  // Contains the commands sent while the authentication is in progress. They
  // will all be executed afterwards. If the device disconnects, they are
  // removed.
  private commandQueue: Command[] = [];

  protected adb: Adb;
  protected state = AdbConnectionState.READY_TO_CONNECT;
  protected device?: USBDevice;

  protected constructor(adb: Adb, consumer: Consumer) {
    super(consumer);
    this.adb = adb;
  }

  async handleCommand(method: string, params: Uint8Array) {
    try {
      if (method === 'FreeBuffers') {
        // When we finish tracing, we disconnect the adb device interface.
        // Otherwise, we will keep holding the device interface and won't allow
        // adb to access it. https://wicg.github.io/webusb/#abusing-a-device
        // "Lastly, since USB devices are unable to distinguish requests from
        // multiple sources, operating systems only allow a USB interface to
        // have a single owning user-space or kernel-space driver."
        this.state = AdbConnectionState.CLOSED;
        await this.adb.disconnect();
      } else if (method === 'EnableTracing') {
        this.state = AdbConnectionState.READY_TO_CONNECT;
      }

      if (this.state === AdbConnectionState.CLOSED) return;

      this.commandQueue.push({method, params});

      if (
        this.state === AdbConnectionState.READY_TO_CONNECT ||
        this.deviceDisconnected()
      ) {
        this.state = AdbConnectionState.AUTH_IN_PROGRESS;
        this.device = await this.findDevice();
        if (!this.device) {
          this.state = AdbConnectionState.READY_TO_CONNECT;
          const target = globals.state.recordingTarget;
          throw Error(
            `Device with serial ${
              isAdbTarget(target) ? target.serial : 'n/a'
            } not found.`,
          );
        }

        this.sendStatus(`Please allow USB debugging on device.
          If you press cancel, reload the page.`);

        await this.adb.connect(this.device);

        // During the authentication the device may have been disconnected.
        if (!globals.state.recordingInProgress || this.deviceDisconnected()) {
          throw Error('Recording not in progress after adb authorization.');
        }

        this.state = AdbConnectionState.CONNECTED;
        this.sendStatus('Device connected.');
      }

      if (this.state === AdbConnectionState.AUTH_IN_PROGRESS) return;

      console.assert(this.state === AdbConnectionState.CONNECTED);

      for (const cmd of this.commandQueue) this.invoke(cmd.method, cmd.params);

      this.commandQueue = [];
    } catch (e) {
      this.commandQueue = [];
      this.state = AdbConnectionState.READY_TO_CONNECT;
      this.sendErrorMessage(e.message);
    }
  }

  private deviceDisconnected() {
    return !this.device || !this.device.opened;
  }

  setDurationStatus(enableTracingProto: Uint8Array) {
    const traceConfigProto = extractTraceConfig(enableTracingProto);
    if (!traceConfigProto) return;
    const duration = extractDurationFromTraceConfig(traceConfigProto);
    this.sendStatus(
      `Recording in progress${
        exists(duration) ? ' for ' + duration.toString() + ' ms' : ''
      }...`,
    );
  }

  abstract invoke(method: string, argsProto: Uint8Array): void;

  generateChunkReadResponse(
    data: Uint8Array,
    last = false,
  ): ReadBuffersResponse {
    return {
      type: 'ReadBuffersResponse',
      slices: [{data, lastSliceForPacket: last}],
    };
  }

  async findDevice(): Promise<USBDevice | undefined> {
    if (!('usb' in navigator)) return undefined;
    const connectedDevice = globals.state.recordingTarget;
    if (!isAdbTarget(connectedDevice)) return undefined;
    const devices = await navigator.usb.getDevices();
    return devices.find((d) => d.serialNumber === connectedDevice.serial);
  }
}
