// Copyright 2022 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/pwpb/internal/method_union.h"

#include <array>

#include "gtest/gtest.h"
#include "pw_rpc/internal/test_utils.h"
#include "pw_rpc_pwpb_private/internal_test_utils.h"
#include "pw_rpc_test_protos/test.pwpb.h"

namespace pw::rpc::internal {
namespace {

using std::byte;

template <typename Implementation>
class FakeGeneratedService : public Service {
 public:
  constexpr FakeGeneratedService(uint32_t id) : Service(id, kMethods) {}

  static constexpr std::array<PwpbMethodUnion, 4> kMethods = {
      GetPwpbOrRawMethodFor<&Implementation::DoNothing,
                            MethodType::kUnary,
                            pw::rpc::test::Empty::Message,
                            pw::rpc::test::Empty::Message>(
          10u,
          kPwpbMethodSerde<&pw::rpc::test::Empty::kMessageFields,
                           &pw::rpc::test::Empty::kMessageFields>),
      GetPwpbOrRawMethodFor<&Implementation::RawStream,
                            MethodType::kServerStreaming,
                            pw::rpc::test::TestRequest::Message,
                            pw::rpc::test::TestResponse::Message>(
          11u,
          kPwpbMethodSerde<&pw::rpc::test::TestRequest::kMessageFields,
                           &pw::rpc::test::TestResponse::kMessageFields>),
      GetPwpbOrRawMethodFor<&Implementation::AddFive,
                            MethodType::kUnary,
                            pw::rpc::test::TestRequest::Message,
                            pw::rpc::test::TestResponse::Message>(
          12u,
          kPwpbMethodSerde<&pw::rpc::test::TestRequest::kMessageFields,
                           &pw::rpc::test::TestResponse::kMessageFields>),
      GetPwpbOrRawMethodFor<&Implementation::StartStream,
                            MethodType::kServerStreaming,
                            pw::rpc::test::TestRequest::Message,
                            pw::rpc::test::TestResponse::Message>(
          13u,
          kPwpbMethodSerde<&pw::rpc::test::TestRequest::kMessageFields,
                           &pw::rpc::test::TestResponse::kMessageFields>),
  };
};

class FakeGeneratedServiceImpl
    : public FakeGeneratedService<FakeGeneratedServiceImpl> {
 public:
  FakeGeneratedServiceImpl(uint32_t id) : FakeGeneratedService(id) {}

  Status AddFive(const pw::rpc::test::TestRequest::Message& request,
                 pw::rpc::test::TestResponse::Message& response) {
    last_request = request;
    response.value = request.integer + 5;
    return Status::Unauthenticated();
  }

  void DoNothing(ConstByteSpan, RawUnaryResponder& responder) {
    ASSERT_EQ(OkStatus(), responder.Finish({}, Status::Unknown()));
  }

  void RawStream(ConstByteSpan, RawServerWriter& writer) {
    last_raw_writer = std::move(writer);
  }

  void StartStream(
      const pw::rpc::test::TestRequest::Message& request,
      PwpbServerWriter<pw::rpc::test::TestResponse::Message>& writer) {
    last_request = request;
    last_writer = std::move(writer);
  }

  pw::rpc::test::TestRequest::Message last_request;
  PwpbServerWriter<pw::rpc::test::TestResponse::Message> last_writer;
  RawServerWriter last_raw_writer;
};

TEST(PwpbMethodUnion, Raw_CallsUnaryMethod) {
  const Method& method =
      std::get<0>(FakeGeneratedServiceImpl::kMethods).method();
  ServerContextForTest<FakeGeneratedServiceImpl> context(method);
  rpc_lock().lock();
  method.Invoke(context.get(), context.request({}));

  const Packet& response = context.output().last_packet();
  EXPECT_EQ(response.status(), Status::Unknown());
}

TEST(PwpbMethodUnion, Raw_CallsServerStreamingMethod) {
  PW_ENCODE_PB(
      pw::rpc::test::TestRequest, request, .integer = 555, .status_code = 0);

  const Method& method =
      std::get<1>(FakeGeneratedServiceImpl::kMethods).method();
  ServerContextForTest<FakeGeneratedServiceImpl> context(method);

  rpc_lock().lock();
  method.Invoke(context.get(), context.request(request));

  EXPECT_TRUE(context.service().last_raw_writer.active());
  EXPECT_EQ(OkStatus(), context.service().last_raw_writer.Finish());
  EXPECT_EQ(context.output().last_packet().type(), PacketType::RESPONSE);
}

TEST(PwpbMethodUnion, Pwpb_CallsUnaryMethod) {
  PW_ENCODE_PB(
      pw::rpc::test::TestRequest, request, .integer = 123, .status_code = 3);

  const Method& method =
      std::get<2>(FakeGeneratedServiceImpl::kMethods).method();
  ServerContextForTest<FakeGeneratedServiceImpl> context(method);
  rpc_lock().lock();
  method.Invoke(context.get(), context.request(request));

  const Packet& response = context.output().last_packet();
  EXPECT_EQ(response.status(), Status::Unauthenticated());

  // Field 1 (encoded as 1 << 3) with 128 as the value.
  constexpr std::byte expected[]{
      std::byte{0x08}, std::byte{0x80}, std::byte{0x01}};

  EXPECT_EQ(sizeof(expected), response.payload().size());
  EXPECT_EQ(0,
            std::memcmp(expected, response.payload().data(), sizeof(expected)));

  EXPECT_EQ(123, context.service().last_request.integer);
  EXPECT_EQ(3u, context.service().last_request.status_code);
}

TEST(PwpbMethodUnion, Pwpb_CallsServerStreamingMethod) {
  PW_ENCODE_PB(
      pw::rpc::test::TestRequest, request, .integer = 555, .status_code = 0);

  const Method& method =
      std::get<3>(FakeGeneratedServiceImpl::kMethods).method();
  ServerContextForTest<FakeGeneratedServiceImpl> context(method);

  rpc_lock().lock();
  method.Invoke(context.get(), context.request(request));

  EXPECT_EQ(555, context.service().last_request.integer);
  EXPECT_TRUE(context.service().last_writer.active());

  EXPECT_EQ(OkStatus(), context.service().last_writer.Finish());
  EXPECT_EQ(context.output().last_packet().type(), PacketType::RESPONSE);
}

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