// 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/responder.h"

#include <algorithm>
#include <array>
#include <cstdint>
#include <cstring>

#include "gtest/gtest.h"
#include "pw_rpc/internal/test_method.h"
#include "pw_rpc/server_context.h"
#include "pw_rpc/service.h"
#include "pw_rpc_private/internal_test_utils.h"

namespace pw::rpc {

class TestService : public Service {
 public:
  constexpr TestService(uint32_t id) : Service(id, method) {}

  static constexpr internal::TestMethodUnion method = internal::TestMethod(8);
};

namespace internal {
namespace {

using std::byte;

TEST(Responder, ConstructWithContext_StartsOpen) {
  ServerContextForTest<TestService> context(TestService::method.method());

  Responder writer(context.get());

  EXPECT_TRUE(writer.open());
}

TEST(Responder, Move_ClosesOriginal) {
  ServerContextForTest<TestService> context(TestService::method.method());

  Responder moved(context.get());
  Responder writer(std::move(moved));

#ifndef __clang_analyzer__
  EXPECT_FALSE(moved.open());
#endif  // ignore use-after-move
  EXPECT_TRUE(writer.open());
}

class FakeServerWriter : public Responder {
 public:
  FakeServerWriter(ServerCall& context) : Responder(context) {}

  constexpr FakeServerWriter() = default;

  Status Write(std::span<const byte> response) {
    std::span buffer = AcquirePayloadBuffer();
    std::memcpy(buffer.data(),
                response.data(),
                std::min(buffer.size(), response.size()));
    return ReleasePayloadBuffer(buffer.first(response.size()));
  }

  ByteSpan PayloadBuffer() { return AcquirePayloadBuffer(); }
  const Channel::OutputBuffer& output_buffer() { return buffer(); }
};

TEST(ServerWriter, DefaultConstruct_Closed) {
  FakeServerWriter writer;

  EXPECT_FALSE(writer.open());
}

TEST(ServerWriter, Construct_RegistersWithServer) {
  ServerContextForTest<TestService> context(TestService::method.method());
  FakeServerWriter writer(context.get());

  auto& writers = context.server().writers();
  EXPECT_FALSE(writers.empty());
  auto it = std::find_if(
      writers.begin(), writers.end(), [&](auto& w) { return &w == &writer; });
  ASSERT_NE(it, writers.end());
}

TEST(ServerWriter, Destruct_RemovesFromServer) {
  ServerContextForTest<TestService> context(TestService::method.method());
  { FakeServerWriter writer(context.get()); }

  auto& writers = context.server().writers();
  EXPECT_TRUE(writers.empty());
}

TEST(ServerWriter, Finish_RemovesFromServer) {
  ServerContextForTest<TestService> context(TestService::method.method());
  FakeServerWriter writer(context.get());

  EXPECT_EQ(OkStatus(), writer.Finish());

  auto& writers = context.server().writers();
  EXPECT_TRUE(writers.empty());
}

TEST(ServerWriter, Finish_SendsResponse) {
  ServerContextForTest<TestService> context(TestService::method.method());
  FakeServerWriter writer(context.get());

  EXPECT_EQ(OkStatus(), writer.Finish());

  const Packet& packet = context.output().sent_packet();
  EXPECT_EQ(packet.type(), PacketType::RESPONSE);
  EXPECT_EQ(packet.channel_id(), context.channel_id());
  EXPECT_EQ(packet.service_id(), context.service_id());
  EXPECT_EQ(packet.method_id(), context.get().method().id());
  EXPECT_TRUE(packet.payload().empty());
  EXPECT_EQ(packet.status(), OkStatus());
}

TEST(ServerWriter, Finish_ReturnsStatusFromChannelSend) {
  ServerContextForTest<TestService> context(TestService::method.method());
  FakeServerWriter writer(context.get());
  context.output().set_send_status(Status::Unauthenticated());

  EXPECT_EQ(Status::Unauthenticated(), writer.Finish());
}

TEST(ServerWriter, Close) {
  ServerContextForTest<TestService> context(TestService::method.method());
  FakeServerWriter writer(context.get());

  ASSERT_TRUE(writer.open());
  EXPECT_EQ(OkStatus(), writer.Finish());
  EXPECT_FALSE(writer.open());
  EXPECT_EQ(Status::FailedPrecondition(), writer.Finish());
}

TEST(ServerWriter, Close_ReleasesBuffer) {
  ServerContextForTest<TestService> context(TestService::method.method());
  FakeServerWriter writer(context.get());

  ASSERT_TRUE(writer.open());
  auto buffer = writer.PayloadBuffer();
  buffer[0] = std::byte{0};
  EXPECT_FALSE(writer.output_buffer().empty());
  EXPECT_EQ(OkStatus(), writer.Finish());
  EXPECT_FALSE(writer.open());
  EXPECT_TRUE(writer.output_buffer().empty());
}

TEST(ServerWriter, Open_SendsPacketWithPayload) {
  ServerContextForTest<TestService> context(TestService::method.method());
  FakeServerWriter writer(context.get());

  constexpr byte data[] = {byte{0xf0}, byte{0x0d}};
  ASSERT_EQ(OkStatus(), writer.Write(data));

  byte encoded[64];
  auto result = context.server_stream(data).Encode(encoded);
  ASSERT_EQ(OkStatus(), result.status());

  EXPECT_EQ(result.value().size(), context.output().sent_data().size());
  EXPECT_EQ(
      0,
      std::memcmp(
          encoded, context.output().sent_data().data(), result.value().size()));
}

TEST(ServerWriter, Closed_IgnoresFinish) {
  ServerContextForTest<TestService> context(TestService::method.method());
  FakeServerWriter writer(context.get());

  EXPECT_EQ(OkStatus(), writer.Finish());
  EXPECT_EQ(Status::FailedPrecondition(), writer.Finish());
}

}  // namespace
}  // namespace internal
}  // namespace pw::rpc
