// 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 <cstddef>
#include <cstdint>
#include <utility>

#include "pw_rpc/internal/call_context.h"
#include "pw_rpc/server_context.h"

namespace pw::rpc {

class Service;

namespace internal {

class Packet;

// Each supported protobuf implementation provides a class that derives from
// Method. The implementation classes provide the following public interface:
/*
class MethodImpl : public Method {
  // True if the provided function signature is valid for this method impl.
  template <auto kMethod>
  static constexpr bool matches();

  // Creates a unary method instance.
  template <auto kMethod>
  static constexpr MethodImpl Unary(uint32_t id, [optional args]);

  // Creates a server streaming method instance.
  template <auto kMethod>
  static constexpr MethodImpl ServerStreaming(uint32_t id, [optional args]);

  // Creates a client streaming method instance.
  static constexpr MethodImpl ClientStreaming(uint32_t id, [optional args]);

  // Creates a bidirectional streaming method instance.
  static constexpr MethodImpl BidirectionalStreaming(uint32_t id,
                                                     [optional args]);

  // Creates a method instance for when the method implementation function has
  // an incorrect signature. Having this helps reduce error message verbosity.
  static constexpr MethodImpl Invalid();
};
*/
// Method implementations must pass a test that uses the MethodImplTester class
// in pw_rpc/internal/method_impl_tester.h.
class Method {
 public:
  constexpr uint32_t id() const { return id_; }

  // The pw::rpc::Server calls method.Invoke to call a user-defined RPC. Invoke
  // calls the invoker function, which handles the RPC request and response
  // according to the RPC type and protobuf implementation and calls the
  // user-defined RPC function.
  void Invoke(const CallContext& context, const Packet& request) const {
    return invoker_(context, request);
  }

 protected:
  using Invoker = void (&)(const CallContext&, const Packet&);

  static constexpr void InvalidInvoker(const CallContext&, const Packet&) {}

  constexpr Method(uint32_t id, Invoker invoker) : id_(id), invoker_(invoker) {}

 private:
  uint32_t id_;
  Invoker invoker_;
};

// MethodTraits inspects an RPC implementation function. It determines which
// Method API is in use and the type of the RPC based on the function signature.
// pw_rpc Method implementations specialize MethodTraits for each RPC type.
template <typename Method>
struct MethodTraits {
  // Specializations must set Implementation as an alias for their method
  // implementation class.
  using Implementation = Method;

  // Specializations must set kType to the MethodType.
  // static constexpr MethodType kType = (method type);

  // Specializations for member function types must set Service to an alias to
  // for the implemented service class.
  // using Service = (derived service class);

  // Specializations may provide the C++ types of the requests and responses if
  // relevant.
  using Request = void;
  using Response = void;
};

template <auto kMethod>
using MethodImplementation =
    typename MethodTraits<decltype(kMethod)>::Implementation;

template <auto kMethod>
using Request = typename MethodTraits<decltype(kMethod)>::Request;

template <auto kMethod>
using Response = typename MethodTraits<decltype(kMethod)>::Response;

// Function that calls a user-defined RPC function on the given Service.
template <auto kMethod, typename... Args>
constexpr auto CallMethodImplFunction(Service& service, Args&&... args) {
  // If the method impl is a member function, deduce the type of the
  // user-defined service from it, then call the method on the service.
  if constexpr (std::is_member_function_pointer_v<decltype(kMethod)>) {
    return (static_cast<typename MethodTraits<decltype(kMethod)>::Service&>(
                service).*
            kMethod)(GlobalServerContextStub(), std::forward<Args>(args)...);
  } else {
    return kMethod(GlobalServerContextStub(), std::forward<Args>(args)...);
  }
}

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