// Copyright 2021 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 {Message} from 'google-protobuf';
import {Status} from '@pigweed/pw_status';

import {Call} from './call';
import {Channel, Method, Service} from './descriptors';
import * as packets from './packets';

/** Data class for a pending RPC call. */
export class Rpc {
  readonly channel: Channel;
  readonly service: Service;
  readonly method: Method;

  constructor(channel: Channel, service: Service, method: Method) {
    this.channel = channel;
    this.service = service;
    this.method = method;
  }

  /** Returns channel service method id tuple */
  get idSet(): [number, number, number] {
    return [this.channel.id, this.service.id, this.method.id];
  }

  /**
   * Returns a string sequence to uniquely identify channel, service, and
   * method. This can be used to hash the Rpc.
   *
   * For example: "12346789.23452345.12341234"
   */
  get idString(): string {
    return `${this.channel.id}.${this.service.id}.${this.method.id}`;
  }

  toString(): string {
    return `${this.service.name}.${this.method.name} on channel ` +
        `${this.channel.id}`;
  }
}

/** Tracks pending RPCs and encodes outgoing RPC packets. */
export class PendingCalls {
  pending: Map<string, Call> = new Map;

  /** Starts the provided RPC and returns the encoded packet to send. */
  request(rpc: Rpc, request: Message, call: Call): Uint8Array {
    this.open(rpc, call)
    console.log(`Starting ${rpc}`);
    return packets.encodeRequest(rpc.idSet, request);
  }

  /** Calls request and sends the resulting packet to the channel. */
  sendRequest(rpc: Rpc, call: Call, request?: Message): Call|undefined {
    const previous = this.open(rpc, call);
    rpc.channel.send(packets.encodeRequest(rpc.idSet, request));
    return previous;
  }

  /**
   * Creates a call for an RPC, but does not invoke it.
   *
   * open() can be used to receive streaming responses to an RPC that was not
   * invoked by this client. For example, a server may stream logs with a
   * server streaming RPC prior to any clients invoking it.
   */
  open(rpc: Rpc, call: Call): Call|undefined {
    console.debug(`Starting ${rpc}`);
    const previous = this.pending.get(rpc.idString);
    this.pending.set(rpc.idString, call)
    return previous;
  }

  sendClientStream(rpc: Rpc, message: Message) {
    if (this.getPending(rpc) === undefined) {
      throw new Error(`Attempt to send client stream for inactive RPC: ${rpc}`);
    }
    rpc.channel.send(packets.encodeClientStream(rpc.idSet, message));
  }

  sendClientStreamEnd(rpc: Rpc) {
    if (this.getPending(rpc) === undefined) {
      throw new Error(`Attempt to send client stream for inactive RPC: ${rpc}`);
    }
    rpc.channel.send(packets.encodeClientStreamEnd(rpc.idSet));
  }

  /** Cancels the RPC. Returns the CANCEL packet to send. */
  cancel(rpc: Rpc): Uint8Array|undefined {
    console.debug(`Cancelling ${rpc}`);
    this.pending.delete(rpc.idString);
    if (rpc.method.clientStreaming && rpc.method.serverStreaming) {
      return undefined;
    }
    return packets.encodeCancel(rpc.idSet);
  }

  /** Calls cancel and sends the cancel packet, if any, to the channel. */
  sendCancel(rpc: Rpc): boolean {
    let packet: Uint8Array|undefined;
    try {
      packet = this.cancel(rpc);
    } catch (err) {
      return false;
    }

    if (packet !== undefined) {
      rpc.channel.send(packet);
    }
    return true;
  }

  /** Gets the pending RPC's call. If status is set, clears the RPC. */
  getPending(rpc: Rpc, status?: Status): Call|undefined {
    if (status === undefined) {
      return this.pending.get(rpc.idString);
    }

    const call = this.pending.get(rpc.idString);
    this.pending.delete(rpc.idString);
    return call;
  }
}
