// 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.
#pragma once

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <span>
#include <type_traits>

#include "pw_rpc/internal/base_server_writer.h"
#include "pw_rpc/internal/method.h"
#include "pw_rpc/internal/method_type.h"
#include "pw_rpc/internal/nanopb_common.h"
#include "pw_rpc/server_context.h"
#include "pw_status/status.h"
#include "pw_status/status_with_size.h"

namespace pw::rpc {

// Define the Nanopb version of the the ServerWriter class.
template <typename T>
class ServerWriter : public internal::BaseServerWriter {
 public:
  // Allow default construction so that users can declare a variable into which
  // to move ServerWriters from RPC calls.
  constexpr ServerWriter() = default;

  ServerWriter(ServerWriter&&) = default;
  ServerWriter& operator=(ServerWriter&&) = default;

  // 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 T& response);
};

namespace internal {

class Packet;

// Templated false value for use in static_assert(false) statements.
template <typename...>
constexpr std::false_type kFalseValue{};

// Extracts the request and response proto types from a method.
template <typename Method>
struct RpcTraits {
  static_assert(kFalseValue<Method>,
                "The selected function is not an RPC service method");
};

// Specialization for unary RPCs.
template <typename RequestType, typename ResponseType>
struct RpcTraits<Status (*)(ServerCall&, const RequestType&, ResponseType&)> {
  using Request = RequestType;
  using Response = ResponseType;

  static constexpr MethodType kType = MethodType::kUnary;
  static constexpr bool kServerStreaming = false;
  static constexpr bool kClientStreaming = false;
};

// Specialization for server streaming RPCs.
template <typename RequestType, typename ResponseType>
struct RpcTraits<void (*)(
    ServerCall&, const RequestType&, ServerWriter<ResponseType>&)> {
  using Request = RequestType;
  using Response = ResponseType;

  static constexpr MethodType kType = MethodType::kServerStreaming;
  static constexpr bool kServerStreaming = true;
  static constexpr bool kClientStreaming = false;
};

// Member function specialization for unary RPCs.
template <typename T, typename RequestType, typename ResponseType>
struct RpcTraits<Status (T::*)(
    ServerContext&, const RequestType&, ResponseType&)>
    : public RpcTraits<Status (*)(
          ServerCall&, const RequestType&, ResponseType&)> {
  using Service = T;
};

// Member function specialization for server streaming RPCs.
template <typename T, typename RequestType, typename ResponseType>
struct RpcTraits<void (T::*)(
    ServerContext&, const RequestType&, ServerWriter<ResponseType>&)>
    : public RpcTraits<void (*)(
          ServerCall&, const RequestType&, ServerWriter<ResponseType>&)> {
  using Service = T;
};

template <auto method>
using Request = typename RpcTraits<decltype(method)>::Request;

template <auto method>
using Response = typename RpcTraits<decltype(method)>::Response;

// The NanopbMethod class invokes user-defined service methods. When a
// pw::rpc::Server receives an RPC request packet, it looks up the matching
// NanopbMethod instance and calls its Invoke method, which eventually calls
// into the user-defined RPC function.
//
// A NanopbMethod instance is created for each user-defined RPC in the pw_rpc
// generated code. The NanopbMethod stores a pointer to the RPC function, a
// pointer to an "invoker" function that calls that function, and pointers to
// the Nanopb descriptors used to encode and decode request and response
// structs.
class NanopbMethod : public Method {
 public:
  // Creates a NanopbMethod for a unary RPC.
  template <auto method>
  static constexpr NanopbMethod Unary(uint32_t id,
                                      NanopbMessageDescriptor request,
                                      NanopbMessageDescriptor response) {
    // Define a wrapper around the user-defined function that takes the
    // request and response protobuf structs as void*. This wrapper is stored
    // generically in the Function union, defined below.
    //
    // In optimized builds, the compiler inlines the user-defined function into
    // this wrapper, elminating any overhead.
    return NanopbMethod(
        id,
        UnaryInvoker<AllocateSpaceFor<Request<method>>(),
                     AllocateSpaceFor<Response<method>>()>,
        Function{.unary =
                     [](ServerCall& call, const void* req, void* resp) {
                       return method(call,
                                     *static_cast<const Request<method>*>(req),
                                     *static_cast<Response<method>*>(resp));
                     }},
        request,
        response);
  }

  // Creates a NanopbMethod for a server-streaming RPC.
  template <auto method>
  static constexpr NanopbMethod ServerStreaming(
      uint32_t id,
      NanopbMessageDescriptor request,
      NanopbMessageDescriptor response) {
    // Define a wrapper around the user-defined function that takes the request
    // struct as void* and a BaseServerWriter instead of the templated
    // ServerWriter class. This wrapper is stored generically in the Function
    // union, defined below.
    return NanopbMethod(
        id,
        ServerStreamingInvoker<AllocateSpaceFor<Request<method>>()>,
        Function{.server_streaming =
                     [](ServerCall& call,
                        const void* req,
                        BaseServerWriter& writer) {
                       method(call,
                              *static_cast<const Request<method>*>(req),
                              static_cast<ServerWriter<Response<method>>&>(
                                  writer));
                     }},
        request,
        response);
  }

  // Encodes a response protobuf with Nanopb to the provided buffer.
  StatusWithSize EncodeResponse(const void* proto_struct,
                                std::span<std::byte> buffer) const {
    return serde_.EncodeResponse(buffer, proto_struct);
  }

  // Decodes a response protobuf with Nanopb to the provided buffer. For testing
  // use.
  bool DecodeResponse(std::span<const std::byte> response,
                      void* proto_struct) const {
    return serde_.DecodeResponse(proto_struct, response);
  }

 private:
  // Generic version of the unary RPC function signature:
  //
  //   Status(ServerCall&, const Request&, Response&)
  //
  using UnaryFunction = Status (*)(ServerCall&,
                                   const void* request,
                                   void* response);

  // Generic version of the server streaming RPC function signature:
  //
  //   Status(ServerCall&, const Request&, ServerWriter<Response>&)
  //
  using ServerStreamingFunction = void (*)(ServerCall&,
                                           const void* request,
                                           BaseServerWriter& writer);

  // The Function union stores a pointer to a generic version of the
  // user-defined RPC function. Using a union instead of void* avoids
  // reinterpret_cast, which keeps this class fully constexpr.
  union Function {
    UnaryFunction unary;
    ServerStreamingFunction server_streaming;
    // TODO(hepler): Add client_streaming and bidi_streaming
  };

  // Allocates space for a struct. Rounds up to a reasonable minimum size to
  // avoid generating unnecessary copies of the invoker functions.
  template <typename T>
  static constexpr size_t AllocateSpaceFor() {
    return std::max(sizeof(T), size_t(64));
  }

  constexpr NanopbMethod(uint32_t id,
                         Invoker invoker,
                         Function function,
                         NanopbMessageDescriptor request,
                         NanopbMessageDescriptor response)
      : Method(id, invoker), function_(function), serde_(request, response) {}

  void CallUnary(ServerCall& call,
                 const Packet& request,
                 void* request_struct,
                 void* response_struct) const;

  void CallServerStreaming(ServerCall& call,
                           const Packet& request,
                           void* request_struct) const;

  // TODO(hepler): Add CallClientStreaming and CallBidiStreaming

  // Invoker function for unary RPCs. Allocates request and response structs by
  // size, with maximum alignment, to avoid generating unnecessary copies of
  // this function for each request/response type.
  template <size_t request_size, size_t response_size>
  static void UnaryInvoker(const Method& method,
                           ServerCall& call,
                           const Packet& request) {
    std::aligned_storage_t<request_size, alignof(std::max_align_t)>
        request_struct{};
    std::aligned_storage_t<response_size, alignof(std::max_align_t)>
        response_struct{};

    static_cast<const NanopbMethod&>(method).CallUnary(
        call, request, &request_struct, &response_struct);
  }

  // Invoker function for server streaming RPCs. Allocates space for a request
  // struct. Ignores the payload buffer since resposnes are sent through the
  // ServerWriter.
  template <size_t request_size>
  static void ServerStreamingInvoker(const Method& method,
                                     ServerCall& call,
                                     const Packet& request) {
    std::aligned_storage_t<request_size, alignof(std::max_align_t)>
        request_struct{};

    static_cast<const NanopbMethod&>(method).CallServerStreaming(
        call, request, &request_struct);
  }

  // Decodes a request protobuf with Nanopb to the provided buffer. Sends an
  // error packet if the request failed to decode.
  bool DecodeRequest(Channel& channel,
                     const Packet& request,
                     void* proto_struct) const;

  // Encodes a response and sends it over the provided channel.
  void SendResponse(Channel& channel,
                    const Packet& request,
                    const void* response_struct,
                    Status status) const;

  // Stores the user-defined RPC in a generic wrapper.
  Function function_;

  // Serde used to encode and decode Nanopb structs.
  NanopbMethodSerde serde_;
};

}  // namespace internal

template <typename T>
Status ServerWriter<T>::Write(const T& response) {
  if (!open()) {
    return Status::FailedPrecondition();
  }

  std::span<std::byte> buffer = AcquirePayloadBuffer();

  if (auto result =
          static_cast<const internal::NanopbMethod&>(method()).EncodeResponse(
              &response, buffer);
      result.ok()) {
    return ReleasePayloadBuffer(buffer.first(result.size()));
  }

  ReleasePayloadBuffer();
  return Status::Internal();
}

}  // namespace pw::rpc
