// 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 {extractDurationFromTraceConfig} from '../base/trace_config_utils';
import {extractTraceConfig} from '../base/trace_config_utils';
import {isAdbTarget} from '../common/state';
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${
        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);
  }
}
