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

#include "pw_rpc/internal/nanopb_method.h"

#include "pb_decode.h"
#include "pb_encode.h"
#include "pw_log/log.h"
#include "pw_rpc/internal/packet.h"

namespace pw::rpc::internal {

using std::byte;

void NanopbMethod::CallUnary(ServerCall& call,
                             const Packet& request,
                             void* request_struct,
                             void* response_struct) const {
  if (!DecodeRequest(call.channel(), request, request_struct)) {
    return;
  }

  const Status status = function_.unary(call, request_struct, response_struct);
  SendResponse(call.channel(), request, response_struct, status);
}

void NanopbMethod::CallServerStreaming(ServerCall& call,
                                       const Packet& request,
                                       void* request_struct) const {
  if (!DecodeRequest(call.channel(), request, request_struct)) {
    return;
  }

  internal::BaseServerWriter server_writer(call);
  function_.server_streaming(call, request_struct, server_writer);
}

bool NanopbMethod::DecodeRequest(Channel& channel,
                                 const Packet& request,
                                 void* proto_struct) const {
  if (serde_.DecodeRequest(proto_struct, request.payload())) {
    return true;
  }

  PW_LOG_WARN("Nanopb failed to decode request payload from channel %u",
              unsigned(channel.id()));
  channel.Send(Packet::ServerError(request, Status::DataLoss()));
  return false;
}

void NanopbMethod::SendResponse(Channel& channel,
                                const Packet& request,
                                const void* response_struct,
                                Status status) const {
  Channel::OutputBuffer response_buffer = channel.AcquireBuffer();
  std::span payload_buffer = response_buffer.payload(request);

  StatusWithSize encoded = EncodeResponse(response_struct, payload_buffer);

  if (encoded.ok()) {
    Packet response = Packet::Response(request);

    response.set_payload(payload_buffer.first(encoded.size()));
    response.set_status(status);
    pw::Status send_status = channel.Send(response_buffer, response);
    if (send_status.ok()) {
      return;
    }

    PW_LOG_WARN("Failed to send response packet for channel %u, status %u",
                unsigned(channel.id()),
                send_status.code());

    // Re-acquire the buffer to encode an error packet.
    response_buffer = channel.AcquireBuffer();
  } else {
    PW_LOG_WARN(
        "Nanopb failed to encode response packet for channel %u, status %u",
        unsigned(channel.id()),
        encoded.status().code());
  }
  channel.Send(response_buffer,
               Packet::ServerError(request, Status::Internal()));
}

}  // namespace pw::rpc::internal
