// Copyright 2020 The Pigweed Authors
//
// 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
//
//     https://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 { Subject } from 'rxjs';


/**
 * AsyncQueue is a queue that allows values to be dequeued
 * before they are enqueued, returning a promise that resolves
 * once the value is available.
 */
class AsyncQueue<T> {
  private queue: T[] = [];
  private requestQueue: Array<(val: T) => unknown> = [];

  /**
   * Enqueue val into the queue.
   * @param {T} val
   */
  enqueue(val: T) {
    const callback = this.requestQueue.shift();
    if (callback) {
      callback(val);
    } else {
      this.queue.push(val);
    }
  }

  /**
   * Dequeue a value from the queue, returning a promise
   * if the queue is empty.
   */
  async dequeue(): Promise<T> {
    const val = this.queue.shift();
    if (val !== undefined) {
      return val;
    } else {
      const queuePromise = new Promise<T>((resolve) => {
        this.requestQueue.push(resolve);
      });
      return queuePromise;
    }
  }
}

/**
 * SerialPortMock is a mock for Chrome's upcoming SerialPort interface.
 * Since pw_web_ui only depends on a subset of the interface, this mock
 * only implements that subset.
 */
class SerialPortMock implements SerialPort {
  private deviceData = new AsyncQueue<{ data?: Uint8Array, done?: boolean, error?: Error }>();

  /**
   * Simulate the device sending data to the browser.
   * @param {Uint8Array} data
   */
  dataFromDevice(data: Uint8Array) {
    this.deviceData.enqueue({ data });
  }

  /**
   * Simulate the device closing the connection with the browser.
   */
  closeFromDevice() {
    this.deviceData.enqueue({
      done: true
    });
  }

  /**
   * Simulate an error in the device's read stream.
   * @param {Error} error
   */
  errorFromDevice(error: Error) {
    this.deviceData.enqueue({
      error
    });
  }

  /**
   * An rxjs subject tracking data sent to the (fake) device.
   */
  dataToDevice = new Subject<Uint8Array>();

  /**
   * The ReadableStream of bytes from the device.
   */
  readable = new ReadableStream<Uint8Array>({
    pull: async (controller) => {
      const { data, done, error } = await this.deviceData.dequeue();
      if (done) {
        controller.close();
        return;
      }
      if (error) {
        throw error;
      }
      if (data) {
        controller.enqueue(data);
      }
    },
  });

  /**
   * The WritableStream of bytes to the device.
   */
  writable = new WritableStream<Uint8Array>({
    write: (chunk) => {
      this.dataToDevice.next(chunk);
    }
  });

  /**
   * A spy for opening the serial port.
   */
  open = jasmine.createSpy('openSpy', async (options?: SerialOptions) => { });

  /**
   * A spy for closing the serial port.
   */
  close = jasmine.createSpy('closeSpy', () => { });
}


export class SerialMock implements Serial {
  serialPort = new SerialPortMock();
  dataToDevice = this.serialPort.dataToDevice;
  dataFromDevice = (data: Uint8Array) => { this.serialPort.dataFromDevice(data); };
  closeFromDevice = () => { this.serialPort.closeFromDevice(); };
  errorFromDevice = (error: Error) => { this.serialPort.errorFromDevice(error); }

  /**
   * Request the port from the browser.
   */
  async requestPort(options?: SerialPortRequestOptions) {
    return this.serialPort;
  };

  // The rest of the methods are unimplemented
  // and only exist to ensure SerialMock implements Serial

  onconnect(): ((this: this, ev: SerialConnectionEvent) => any) | null {
    throw new Error('Method not implemented.');
  }

  ondisconnect(): ((this: this, ev: SerialConnectionEvent) => any) | null {
    throw new Error('Method not implemented.');
  }

  getPorts(): Promise<SerialPort[]> {
    throw new Error('Method not implemented.');
  }

  addEventListener(type: 'connect' | 'disconnect',
    listener: (this: this, ev: SerialConnectionEvent) => any,
    useCapture?: boolean): void;

  addEventListener(type: string,
    listener: EventListener | EventListenerObject | null,
    options?: boolean | AddEventListenerOptions): void;

  addEventListener(type: any, listener: any, options?: any) {
    throw new Error('Method not implemented.');
  }

  removeEventListener(type: 'connect' | 'disconnect',
    callback: (this: this, ev: SerialConnectionEvent) => any,
    useCapture?: boolean): void;

  removeEventListener(type: string,
    callback: EventListener | EventListenerObject | null,
    options?: boolean | EventListenerOptions): void;

  removeEventListener(type: any, callback: any, options?: any) {
    throw new Error('Method not implemented.');
  }

  dispatchEvent(event: Event): boolean {
    throw new Error('Method not implemented.');
  }
}
