// 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 <tuple>
#include <type_traits>

#include "gtest/gtest.h"
#include "pw_rpc/internal/packet.h"
#include "pw_rpc/raw/internal/method.h"

namespace pw::rpc::internal {

template <typename...>
struct MatchesTypes {};

// This class tests Method implementation classes and MethodTraits
// specializations. It verifies that they provide the expected functions and
// that they correctly identify and construct the various method types.
//
// The TestService class must inherit from Service and provide the following
// methods with valid signatures for RPCs:
//
//   - Unary: synchronous unary RPC member function
//   - StaticUnary: synchronous unary RPC static member function
//   - AsyncUnary: asynchronous unary RPC member function
//   - StaticAsyncUnary: asynchronous unary RPC static member function
//   - ServerStreaming: server streaming RPC member function
//   - StaticServerStreaming: server streaming static RPC member function
//   - ClientStreaming: client streaming RPC member function
//   - StaticClientStreaming: client streaming static RPC member function
//   - BidirectionalStreaming: bidirectional streaming RPC member function
//   - StaticBidirectionalStreaming: bidirectional streaming static RPC
//         member function
//
template <typename MethodImpl, typename TestService>
class MethodImplTests {
 public:
  template <typename... ExtraTypes, typename... CreationArgs>
  constexpr bool Pass(
      const MatchesTypes<ExtraTypes...>& = {},
      const std::tuple<CreationArgs...>& creation_args = {}) const {
    return Matches<ExtraTypes...>().Pass() && Type().Pass() &&
           Creation().Pass(creation_args);
  }

 private:
  template <typename... ExtraTypes>
  struct Matches {
    constexpr bool Pass() const { return true; }

    // Test that the matches() function matches valid signatures.
    static_assert(
        MethodImpl::template matches<&TestService::Unary, ExtraTypes...>());
    static_assert(MethodImpl::template matches<&TestService::StaticUnary,
                                               ExtraTypes...>());

    static_assert(MethodImpl::template matches<&TestService::AsyncUnary,
                                               ExtraTypes...>());
    static_assert(MethodImpl::template matches<&TestService::StaticAsyncUnary,
                                               ExtraTypes...>());

    static_assert(MethodImpl::template matches<&TestService::ServerStreaming,
                                               ExtraTypes...>());
    static_assert(
        MethodImpl::template matches<&TestService::StaticServerStreaming,
                                     ExtraTypes...>());

    static_assert(MethodImpl::template matches<&TestService::ClientStreaming,
                                               ExtraTypes...>());
    static_assert(
        MethodImpl::template matches<&TestService::StaticClientStreaming,
                                     ExtraTypes...>());

    static_assert(
        MethodImpl::template matches<&TestService::BidirectionalStreaming,
                                     ExtraTypes...>());
    static_assert(
        MethodImpl::template matches<&TestService::StaticBidirectionalStreaming,
                                     ExtraTypes...>());

    // Test that the matches() function does not match the wrong method type.
    static_assert(!MethodImpl::template matches<&TestService::UnaryWrongArg,
                                                ExtraTypes...>());
    static_assert(
        !MethodImpl::template matches<&TestService::StaticUnaryVoidReturn,
                                      ExtraTypes...>());

    static_assert(
        !MethodImpl::template matches<&TestService::ServerStreamingBadReturn,
                                      ExtraTypes...>());
    static_assert(!MethodImpl::template matches<
                  &TestService::StaticServerStreamingMissingArg,
                  ExtraTypes...>());

    static_assert(
        !MethodImpl::template matches<&TestService::ClientStreamingBadReturn,
                                      ExtraTypes...>());
    static_assert(!MethodImpl::template matches<
                  &TestService::StaticClientStreamingMissingArg,
                  ExtraTypes...>());

    static_assert(!MethodImpl::template matches<
                  &TestService::BidirectionalStreamingBadReturn,
                  ExtraTypes...>());
    static_assert(!MethodImpl::template matches<
                  &TestService::StaticBidirectionalStreamingMissingArg,
                  ExtraTypes...>());
  };

  // Check that MethodTraits resolves to the correct value for kType.
  struct Type {
    constexpr bool Pass() const { return true; }

    static_assert(MethodTraits<decltype(&TestService::Unary)>::kType ==
                  MethodType::kUnary);
    static_assert(MethodTraits<decltype(&TestService::Unary)>::kSynchronous);
    static_assert(MethodTraits<decltype(&TestService::StaticUnary)>::kType ==
                  MethodType::kUnary);
    static_assert(
        MethodTraits<decltype(&TestService::StaticUnary)>::kSynchronous);

    static_assert(MethodTraits<decltype(&TestService::AsyncUnary)>::kType ==
                  MethodType::kUnary);
    static_assert(
        !MethodTraits<decltype(&TestService::AsyncUnary)>::kSynchronous);
    static_assert(
        MethodTraits<decltype(&TestService::StaticAsyncUnary)>::kType ==
        MethodType::kUnary);
    static_assert(
        !MethodTraits<decltype(&TestService::StaticAsyncUnary)>::kSynchronous);

    static_assert(
        MethodTraits<decltype(&TestService::ServerStreaming)>::kType ==
        MethodType::kServerStreaming);
    static_assert(
        MethodTraits<decltype(&TestService::StaticServerStreaming)>::kType ==
        MethodType::kServerStreaming);

    static_assert(
        MethodTraits<decltype(&TestService::ClientStreaming)>::kType ==
        MethodType::kClientStreaming);
    static_assert(
        MethodTraits<decltype(&TestService::StaticClientStreaming)>::kType ==
        MethodType::kClientStreaming);

    static_assert(
        MethodTraits<decltype(&TestService::BidirectionalStreaming)>::kType ==
        MethodType::kBidirectionalStreaming);
    static_assert(
        MethodTraits<
            decltype(&TestService::StaticBidirectionalStreaming)>::kType ==
        MethodType::kBidirectionalStreaming);
  };

  // Test method creation.
  class Creation {
   public:
    template <typename... Args>
    constexpr bool Pass(const std::tuple<Args...>& args) const {
      return UnaryMethod(args).id() == 1 && StaticUnaryMethod(args).id() == 2 &&
             AsyncUnaryMethod(args).id() == 3 &&
             StaticAsyncUnaryMethod(args).id() == 4 &&
             ServerStreamingMethod(args).id() == 5 &&
             StaticServerStreamingMethod(args).id() == 6 &&
             ClientStreamingMethod(args).id() == 7 &&
             StaticClientStreamingMethod(args).id() == 8 &&
             BidirectionalStreamingMethod(args).id() == 9 &&
             StaticBidirectionalStreamingMethod(args).id() == 10 &&
             InvalidMethod().id() == 0;
    }

   private:
    template <typename... Args>
    constexpr MethodImpl UnaryMethod(const std::tuple<Args...>& args) const {
      return Call(
          MethodImpl::template SynchronousUnary<&TestService::Unary>, 1, args);
    }

    template <typename... Args>
    constexpr MethodImpl StaticUnaryMethod(
        const std::tuple<Args...>& args) const {
      return Call(
          MethodImpl::template SynchronousUnary<&TestService::StaticUnary>,
          2,
          args);
    }

    template <typename... Args>
    constexpr MethodImpl AsyncUnaryMethod(
        const std::tuple<Args...>& args) const {
      return Call(
          MethodImpl::template AsynchronousUnary<&TestService::AsyncUnary>,
          3,
          args);
    }

    template <typename... Args>
    constexpr MethodImpl StaticAsyncUnaryMethod(
        const std::tuple<Args...>& args) const {
      return Call(MethodImpl::template AsynchronousUnary<
                      &TestService::StaticAsyncUnary>,
                  4,
                  args);
    }

    template <typename... Args>
    constexpr MethodImpl ServerStreamingMethod(
        const std::tuple<Args...>& args) const {
      return Call(
          MethodImpl::template ServerStreaming<&TestService::ServerStreaming>,
          5,
          args);
    }

    template <typename... Args>
    constexpr MethodImpl StaticServerStreamingMethod(
        const std::tuple<Args...>& args) const {
      return Call(MethodImpl::template ServerStreaming<
                      &TestService::StaticServerStreaming>,
                  6,
                  args);
    }

    template <typename... Args>
    constexpr MethodImpl ClientStreamingMethod(
        const std::tuple<Args...>& args) const {
      return Call(
          MethodImpl::template ClientStreaming<&TestService::ClientStreaming>,
          7,
          args);
    }

    template <typename... Args>
    constexpr MethodImpl StaticClientStreamingMethod(
        const std::tuple<Args...>& args) const {
      return Call(MethodImpl::template ClientStreaming<
                      &TestService::StaticClientStreaming>,
                  8,
                  args);
    }

    template <typename... Args>
    constexpr MethodImpl BidirectionalStreamingMethod(
        const std::tuple<Args...>& args) const {
      return Call(MethodImpl::template BidirectionalStreaming<
                      &TestService::BidirectionalStreaming>,
                  9,
                  args);
    }

    template <typename... Args>
    constexpr MethodImpl StaticBidirectionalStreamingMethod(
        const std::tuple<Args...>& args) const {
      return Call(MethodImpl::template BidirectionalStreaming<
                      &TestService::StaticBidirectionalStreaming>,
                  10,
                  args);
    }

    // Test that there is an Invalid method creation function.
    constexpr MethodImpl InvalidMethod() const { return MethodImpl::Invalid(); }

    // Invokes the method creation function with the ID and extra args.
    template <typename Function, typename... Args>
    static constexpr MethodImpl Call(Function&& function,
                                     uint32_t id,
                                     const std::tuple<Args...>& args) {
      return std::apply(function, std::tuple_cat(std::tuple(id), args));
    }
  };
};

}  // namespace pw::rpc::internal
