// 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.

// This file defines the ServerReaderWriter, ServerReader, and ServerWriter
// classes for the Nanopb RPC interface. These classes are used for
// bidirectional, client, and server streaming RPCs.
#pragma once

#include "pw_bytes/span.h"
#include "pw_rpc/channel.h"
#include "pw_rpc/internal/call.h"
#include "pw_rpc/internal/method_lookup.h"
#include "pw_rpc/internal/open_call.h"
#include "pw_rpc/server.h"

namespace pw::rpc {
namespace internal {

// Forward declarations for internal classes needed in friend statements.
class NanopbMethod;

namespace test {

template <typename, typename, uint32_t>
class InvocationContext;

}  // namespace test

// Non-templated base so the methods are instantiated only once.
class GenericNanopbResponder : public internal::Call {
 public:
  constexpr GenericNanopbResponder(MethodType type) : internal::Call(type) {}

  GenericNanopbResponder(const CallContext& call, MethodType type)
      : internal::Call(call, type) {}

  Status SendResponse(const void* response, Status status) {
    return SendClientStreamOrResponse(response, &status);
  }

 protected:
  Status SendClientStream(const void* response) {
    return SendClientStreamOrResponse(response, nullptr);
  }

  void DecodeRequest(ConstByteSpan payload, void* request_struct) const;

 private:
  Status SendClientStreamOrResponse(const void* response, const Status* status);
};

// The BaseNanopbServerReader serves as the base for the ServerReader and
// ServerReaderWriter classes. It adds a callback templated on the request
// struct type. It is templated on the Request type only.
template <typename Request>
class BaseNanopbServerReader : public GenericNanopbResponder {
 public:
  BaseNanopbServerReader(const internal::CallContext& call, MethodType type)
      : GenericNanopbResponder(call, type) {}

 protected:
  constexpr BaseNanopbServerReader(MethodType type)
      : GenericNanopbResponder(type) {}

  void set_on_next(Function<void(const Request& request)> on_next) {
    nanopb_on_next_ = std::move(on_next);

    internal::Call::set_on_next([this](ConstByteSpan payload) {
      Request request_struct;
      DecodeRequest(payload, &request_struct);
      nanopb_on_next_(request_struct);
    });
  }

 private:
  Function<void(const Request&)> nanopb_on_next_;
};

}  // namespace internal

// The NanopbServerReaderWriter is used to send and receive messages in a Nanopb
// bidirectional streaming RPC.
template <typename Request, typename Response>
class NanopbServerReaderWriter
    : private internal::BaseNanopbServerReader<Request> {
 public:
  // Creates a NanopbServerReaderWriter that is ready to send responses for a
  // particular RPC. This can be used for testing or to send responses to an RPC
  // that has not been started by a client.
  template <auto kMethod, uint32_t kMethodId, typename ServiceImpl>
  [[nodiscard]] static NanopbServerReaderWriter Open(Server& server,
                                                     uint32_t channel_id,
                                                     ServiceImpl& service) {
    static_assert(std::is_same_v<Request, internal::Request<kMethod>>,
                  "The request type of a NanopbServerReaderWriter must match "
                  "the method.");
    static_assert(std::is_same_v<Response, internal::Response<kMethod>>,
                  "The response type of a NanopbServerReaderWriter must match "
                  "the method.");
    return {internal::OpenCall<kMethod, MethodType::kBidirectionalStreaming>(
        server,
        channel_id,
        service,
        internal::MethodLookup::GetNanopbMethod<ServiceImpl, kMethodId>())};
  }

  constexpr NanopbServerReaderWriter()
      : internal::BaseNanopbServerReader<Request>(
            MethodType::kBidirectionalStreaming) {}

  NanopbServerReaderWriter(NanopbServerReaderWriter&&) = default;
  NanopbServerReaderWriter& operator=(NanopbServerReaderWriter&&) = default;

  using internal::GenericNanopbResponder::active;

  using internal::GenericNanopbResponder::channel_id;

  // Writes a response struct. Returns the following Status codes:
  //
  //   OK - the response was successfully sent
  //   FAILED_PRECONDITION - the writer is closed
  //   INTERNAL - pw_rpc was unable to encode the Nanopb protobuf
  //   other errors - the ChannelOutput failed to send the packet; the error
  //       codes are determined by the ChannelOutput implementation
  //
  Status Write(const Response& response) {
    return internal::GenericNanopbResponder::SendClientStream(&response);
  }

  Status Finish(Status status = OkStatus()) {
    return internal::Call::CloseAndSendResponse(status);
  }

  // Functions for setting RPC event callbacks.
  using internal::BaseNanopbServerReader<Request>::set_on_client_stream_end;
  using internal::BaseNanopbServerReader<Request>::set_on_error;
  using internal::BaseNanopbServerReader<Request>::set_on_next;

 private:
  friend class internal::NanopbMethod;

  template <typename, typename, uint32_t>
  friend class internal::test::InvocationContext;

  NanopbServerReaderWriter(const internal::CallContext& call)
      : internal::BaseNanopbServerReader<Request>(
            call, MethodType::kBidirectionalStreaming) {}
};

// The NanopbServerReader is used to receive messages and send a response in a
// Nanopb client streaming RPC.
template <typename Request, typename Response>
class NanopbServerReader : private internal::BaseNanopbServerReader<Request> {
 public:
  // Creates a NanopbServerReader that is ready to send a response to a
  // particular RPC. This can be used for testing or to finish an RPC that has
  // not been started by the client.
  template <auto kMethod, uint32_t kMethodId, typename ServiceImpl>
  [[nodiscard]] static NanopbServerReader Open(Server& server,
                                               uint32_t channel_id,
                                               ServiceImpl& service) {
    static_assert(
        std::is_same_v<Request, internal::Request<kMethod>>,
        "The request type of a NanopbServerReader must match the method.");
    static_assert(
        std::is_same_v<Response, internal::Response<kMethod>>,
        "The response type of a NanopbServerReader must match the method.");
    return {internal::OpenCall<kMethod, MethodType::kClientStreaming>(
        server,
        channel_id,
        service,
        internal::MethodLookup::GetNanopbMethod<ServiceImpl, kMethodId>())};
  }

  // Allow default construction so that users can declare a variable into which
  // to move NanopbServerReaders from RPC calls.
  constexpr NanopbServerReader()
      : internal::BaseNanopbServerReader<Request>(
            MethodType::kClientStreaming) {}

  NanopbServerReader(NanopbServerReader&&) = default;
  NanopbServerReader& operator=(NanopbServerReader&&) = default;

  using internal::GenericNanopbResponder::active;
  using internal::GenericNanopbResponder::channel_id;

  // Functions for setting RPC event callbacks.
  using internal::BaseNanopbServerReader<Request>::set_on_client_stream_end;
  using internal::BaseNanopbServerReader<Request>::set_on_error;
  using internal::BaseNanopbServerReader<Request>::set_on_next;

  Status Finish(const Response& response, Status status = OkStatus()) {
    return internal::BaseNanopbServerReader<Request>::SendResponse(&response,
                                                                   status);
  }

 private:
  friend class internal::NanopbMethod;

  template <typename, typename, uint32_t>
  friend class internal::test::InvocationContext;

  NanopbServerReader(const internal::CallContext& call)
      : internal::BaseNanopbServerReader<Request>(
            call, MethodType::kClientStreaming) {}
};

// The NanopbServerWriter is used to send responses in a Nanopb server streaming
// RPC.
template <typename Response>
class NanopbServerWriter : private internal::GenericNanopbResponder {
 public:
  // Creates a NanopbServerWriter that is ready to send responses for a
  // particular RPC. This can be used for testing or to send responses to an RPC
  // that has not been started by a client.
  template <auto kMethod, uint32_t kMethodId, typename ServiceImpl>
  [[nodiscard]] static NanopbServerWriter Open(Server& server,
                                               uint32_t channel_id,
                                               ServiceImpl& service) {
    static_assert(
        std::is_same_v<Response, internal::Response<kMethod>>,
        "The response type of a NanopbServerWriter must match the method.");
    return {internal::OpenCall<kMethod, MethodType::kServerStreaming>(
        server,
        channel_id,
        service,
        internal::MethodLookup::GetNanopbMethod<ServiceImpl, kMethodId>())};
  }

  // Allow default construction so that users can declare a variable into which
  // to move ServerWriters from RPC calls.
  constexpr NanopbServerWriter()
      : internal::GenericNanopbResponder(MethodType::kServerStreaming) {}

  NanopbServerWriter(NanopbServerWriter&&) = default;
  NanopbServerWriter& operator=(NanopbServerWriter&&) = default;

  using internal::GenericNanopbResponder::active;
  using internal::GenericNanopbResponder::channel_id;
  using internal::GenericNanopbResponder::open;

  // Writes a response struct. Returns the following Status codes:
  //
  //   OK - the response was successfully sent
  //   FAILED_PRECONDITION - the writer is closed
  //   INTERNAL - pw_rpc was unable to encode the Nanopb protobuf
  //   other errors - the ChannelOutput failed to send the packet; the error
  //       codes are determined by the ChannelOutput implementation
  //
  Status Write(const Response& response) {
    return internal::GenericNanopbResponder::SendClientStream(&response);
  }

  Status Finish(Status status = OkStatus()) {
    return internal::Call::CloseAndSendResponse(status);
  }

 private:
  friend class internal::NanopbMethod;

  template <typename, typename, uint32_t>
  friend class internal::test::InvocationContext;

  NanopbServerWriter(const internal::CallContext& call)
      : internal::GenericNanopbResponder(call, MethodType::kServerStreaming) {}
};

template <typename Response>
class NanopbServerResponder : private internal::GenericNanopbResponder {
 public:
  // Creates a NanopbServerResponder that is ready to send a response for a
  // particular RPC. This can be used for testing or to send responses to an RPC
  // that has not been started by a client.
  template <auto kMethod, uint32_t kMethodId, typename ServiceImpl>
  [[nodiscard]] static NanopbServerResponder Open(Server& server,
                                                  uint32_t channel_id,
                                                  ServiceImpl& service) {
    static_assert(
        std::is_same_v<Response, internal::Response<kMethod>>,
        "The response type of a NanopbServerResponder must match the method.");
    return {internal::OpenCall<kMethod, MethodType::kUnary>(
        server,
        channel_id,
        service,
        internal::MethodLookup::GetNanopbMethod<ServiceImpl, kMethodId>())};
  }

  // Allow default construction so that users can declare a variable into which
  // to move ServerWriters from RPC calls.
  constexpr NanopbServerResponder()
      : internal::GenericNanopbResponder(MethodType::kUnary) {}

  NanopbServerResponder(NanopbServerResponder&&) = default;
  NanopbServerResponder& operator=(NanopbServerResponder&&) = default;

  using internal::GenericNanopbResponder::active;
  using internal::GenericNanopbResponder::channel_id;

  // Sends the response. Returns the following Status codes:
  //
  //   OK - the response was successfully sent
  //   FAILED_PRECONDITION - the writer is closed
  //   INTERNAL - pw_rpc was unable to encode the Nanopb protobuf
  //   other errors - the ChannelOutput failed to send the packet; the error
  //       codes are determined by the ChannelOutput implementation
  //
  Status Finish(const Response& response, Status status = OkStatus()) {
    return internal::GenericNanopbResponder::SendResponse(&response, status);
  }

 private:
  friend class internal::NanopbMethod;

  template <typename, typename, uint32_t>
  friend class internal::test::InvocationContext;

  NanopbServerResponder(const internal::CallContext& call)
      : internal::GenericNanopbResponder(call, MethodType::kUnary) {}
};
// TODO(hepler): "pw::rpc::ServerWriter" should not be specific to Nanopb.
template <typename T>
using ServerWriter = NanopbServerWriter<T>;

}  // namespace pw::rpc
