// Copyright 2019 Google LLC
//
// 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.

#ifndef dap_session_h
#define dap_session_h

#include "future.h"
#include "io.h"
#include "traits.h"
#include "typeinfo.h"
#include "typeof.h"

#include <functional>

namespace dap {

// Forward declarations
struct Request;
struct Response;
struct Event;

////////////////////////////////////////////////////////////////////////////////
// Error
////////////////////////////////////////////////////////////////////////////////

// Error represents an error message in response to a DAP request.
struct Error {
  Error() = default;
  Error(const std::string& error);
  Error(const char* msg, ...);

  // operator bool() returns true if there is an error.
  inline operator bool() const { return message.size() > 0; }

  std::string message;  // empty represents success.
};

////////////////////////////////////////////////////////////////////////////////
// ResponseOrError<T>
////////////////////////////////////////////////////////////////////////////////

// ResponseOrError holds either the response to a DAP request or an error
// message.
template <typename T>
struct ResponseOrError {
  using Request = T;

  inline ResponseOrError() = default;
  inline ResponseOrError(const T& response);
  inline ResponseOrError(T&& response);
  inline ResponseOrError(const Error& error);
  inline ResponseOrError(Error&& error);
  inline ResponseOrError(const ResponseOrError& other);
  inline ResponseOrError(ResponseOrError&& other);

  inline ResponseOrError& operator=(const ResponseOrError& other);
  inline ResponseOrError& operator=(ResponseOrError&& other);

  T response;
  Error error;  // empty represents success.
};

template <typename T>
ResponseOrError<T>::ResponseOrError(const T& resp) : response(resp) {}
template <typename T>
ResponseOrError<T>::ResponseOrError(T&& resp) : response(std::move(resp)) {}
template <typename T>
ResponseOrError<T>::ResponseOrError(const Error& err) : error(err) {}
template <typename T>
ResponseOrError<T>::ResponseOrError(Error&& err) : error(std::move(err)) {}
template <typename T>
ResponseOrError<T>::ResponseOrError(const ResponseOrError& other)
    : response(other.response), error(other.error) {}
template <typename T>
ResponseOrError<T>::ResponseOrError(ResponseOrError&& other)
    : response(std::move(other.response)), error(std::move(other.error)) {}
template <typename T>
ResponseOrError<T>& ResponseOrError<T>::operator=(
    const ResponseOrError& other) {
  response = other.response;
  error = other.error;
  return *this;
}
template <typename T>
ResponseOrError<T>& ResponseOrError<T>::operator=(ResponseOrError&& other) {
  response = std::move(other.response);
  error = std::move(other.error);
  return *this;
}

////////////////////////////////////////////////////////////////////////////////
// Session
////////////////////////////////////////////////////////////////////////////////

// An enum flag that controls how the Session handles invalid data.
enum OnInvalidData {
  // Ignore invalid data.
  kIgnore,
  // Close the underlying reader when invalid data is received.
  kClose,
};

// Session implements a DAP client or server endpoint.
// The general usage is as follows:
// (1) Create a session with Session::create().
// (2) Register request and event handlers with registerHandler().
// (3) Optionally register a protocol error handler with onError().
// (3) Bind the session to the remote endpoint with bind().
// (4) Send requests or events with send().
class Session {
  template <typename F, int N>
  using ParamType = traits::ParameterType<F, N>;

  template <typename T>
  using IsRequest = traits::EnableIfIsType<dap::Request, T>;

  template <typename T>
  using IsEvent = traits::EnableIfIsType<dap::Event, T>;

  template <typename F>
  using IsRequestHandlerWithoutCallback = traits::EnableIf<
      traits::CompatibleWith<F, std::function<void(dap::Request)>>::value>;

  template <typename F, typename CallbackType>
  using IsRequestHandlerWithCallback = traits::EnableIf<traits::CompatibleWith<
      F,
      std::function<void(dap::Request, std::function<void(CallbackType)>)>>::
                                                            value>;

 public:
  virtual ~Session();

  // ErrorHandler is the type of callback function used for reporting protocol
  // errors.
  using ErrorHandler = std::function<void(const char*)>;

  // ClosedHandler is the type of callback function used to signal that a
  // connected endpoint has closed.
  using ClosedHandler = std::function<void()>;

  // create() constructs and returns a new Session.
  static std::unique_ptr<Session> create();

  // Sets how the Session handles invalid data.
  virtual void setOnInvalidData(OnInvalidData) = 0;

  // onError() registers a error handler that will be called whenever a protocol
  // error is encountered.
  // Only one error handler can be bound at any given time, and later calls
  // will replace the existing error handler.
  virtual void onError(const ErrorHandler&) = 0;

  // registerHandler() registers a request handler for a specific request type.
  // The function F must have one of the following signatures:
  //   ResponseOrError<ResponseType>(const RequestType&)
  //   ResponseType(const RequestType&)
  //   Error(const RequestType&)
  template <typename F, typename RequestType = ParamType<F, 0>>
  inline IsRequestHandlerWithoutCallback<F> registerHandler(F&& handler);

  // registerHandler() registers a request handler for a specific request type.
  // The handler has a response callback function for the second argument of the
  // handler function. This callback may be called after the handler has
  // returned.
  // The function F must have the following signature:
  //   void(const RequestType& request,
  //        std::function<void(ResponseType)> response)
  template <typename F,
            typename RequestType = ParamType<F, 0>,
            typename ResponseType = typename RequestType::Response>
  inline IsRequestHandlerWithCallback<F, ResponseType> registerHandler(
      F&& handler);

  // registerHandler() registers a request handler for a specific request type.
  // The handler has a response callback function for the second argument of the
  // handler function. This callback may be called after the handler has
  // returned.
  // The function F must have the following signature:
  //   void(const RequestType& request,
  //        std::function<void(ResponseOrError<ResponseType>)> response)
  template <typename F,
            typename RequestType = ParamType<F, 0>,
            typename ResponseType = typename RequestType::Response>
  inline IsRequestHandlerWithCallback<F, ResponseOrError<ResponseType>>
  registerHandler(F&& handler);

  // registerHandler() registers a event handler for a specific event type.
  // The function F must have the following signature:
  //   void(const EventType&)
  template <typename F, typename EventType = ParamType<F, 0>>
  inline IsEvent<EventType> registerHandler(F&& handler);

  // registerSentHandler() registers the function F to be called when a response
  // of the specific type has been sent.
  // The function F must have the following signature:
  //   void(const ResponseOrError<ResponseType>&)
  template <typename F,
            typename ResponseType = typename ParamType<F, 0>::Request>
  inline void registerSentHandler(F&& handler);

  // send() sends the request to the connected endpoint and returns a
  // future that is assigned the request response or error.
  template <typename T, typename = IsRequest<T>>
  future<ResponseOrError<typename T::Response>> send(const T& request);

  // send() sends the event to the connected endpoint.
  template <typename T, typename = IsEvent<T>>
  void send(const T& event);

  // bind() connects this Session to an endpoint using connect(), and then
  // starts processing incoming messages with startProcessingMessages().
  // onClose is the optional callback which will be called when the session
  // endpoint has been closed.
  inline void bind(const std::shared_ptr<Reader>& reader,
                   const std::shared_ptr<Writer>& writer,
                   const ClosedHandler& onClose);
  inline void bind(const std::shared_ptr<ReaderWriter>& readerWriter,
                   const ClosedHandler& onClose);

  //////////////////////////////////////////////////////////////////////////////
  // Note:
  // Methods and members below this point are for advanced usage, and are more
  // likely to change signature than the methods above.
  // The methods above this point should be sufficient for most use cases.
  //////////////////////////////////////////////////////////////////////////////

  // connect() connects this Session to an endpoint.
  // connect() can only be called once. Repeated calls will raise an error, but
  // otherwise will do nothing.
  // Note: This method is used for explicit control over message handling.
  //       Most users will use bind() instead of calling this method directly.
  virtual void connect(const std::shared_ptr<Reader>&,
                       const std::shared_ptr<Writer>&) = 0;
  inline void connect(const std::shared_ptr<ReaderWriter>&);

  // startProcessingMessages() starts a new thread to receive and dispatch
  // incoming messages.
  // onClose is the optional callback which will be called when the session
  // endpoint has been closed.
  // Note: This method is used for explicit control over message handling.
  //       Most users will use bind() instead of calling this method directly.
  virtual void startProcessingMessages(const ClosedHandler& onClose = {}) = 0;

  // getPayload() blocks until the next incoming message is received, returning
  // the payload or an empty function if the connection was lost. The returned
  // payload is function that can be called on any thread to dispatch the
  // message to the Session handler.
  // Note: This method is used for explicit control over message handling.
  //       Most users will use bind() instead of calling this method directly.
  virtual std::function<void()> getPayload() = 0;

  // The callback function type called when a request handler is invoked, and
  // the request returns a successful result.
  // 'responseTypeInfo' is the type information of the response data structure.
  // 'responseData' is a pointer to response payload data.
  using RequestHandlerSuccessCallback =
      std::function<void(const TypeInfo* responseTypeInfo,
                         const void* responseData)>;

  // The callback function type used to notify when a DAP request fails.
  // 'responseTypeInfo' is the type information of the response data structure.
  // 'message' is the error message
  using RequestHandlerErrorCallback =
      std::function<void(const TypeInfo* responseTypeInfo,
                         const Error& message)>;

  // The callback function type used to invoke a request handler.
  // 'request' is a pointer to the request data structure
  // 'onSuccess' is the function to call if the request completed succesfully.
  // 'onError' is the function to call if the request failed.
  // For each call of the request handler, 'onSuccess' or 'onError' must be
  // called exactly once.
  using GenericRequestHandler =
      std::function<void(const void* request,
                         const RequestHandlerSuccessCallback& onSuccess,
                         const RequestHandlerErrorCallback& onError)>;

  // The callback function type used to handle a response to a request.
  // 'response' is a pointer to the response data structure. May be nullptr.
  // 'error' is a pointer to the reponse error message. May be nullptr.
  // One of 'data' or 'error' will be nullptr.
  using GenericResponseHandler =
      std::function<void(const void* response, const Error* error)>;

  // The callback function type used to handle an event.
  // 'event' is a pointer to the event data structure.
  using GenericEventHandler = std::function<void(const void* event)>;

  // The callback function type used to notify when a response has been sent
  // from this session endpoint.
  // 'response' is a pointer to the response data structure.
  // 'error' is a pointer to the reponse error message. May be nullptr.
  using GenericResponseSentHandler =
      std::function<void(const void* response, const Error* error)>;

  // registerHandler() registers 'handler' as the request handler callback for
  // requests of the type 'typeinfo'.
  virtual void registerHandler(const TypeInfo* typeinfo,
                               const GenericRequestHandler& handler) = 0;

  // registerHandler() registers 'handler' as the event handler callback for
  // events of the type 'typeinfo'.
  virtual void registerHandler(const TypeInfo* typeinfo,
                               const GenericEventHandler& handler) = 0;

  // registerHandler() registers 'handler' as the response-sent handler function
  // which is called whenever a response of the type 'typeinfo' is sent from
  // this session endpoint.
  virtual void registerHandler(const TypeInfo* typeinfo,
                               const GenericResponseSentHandler& handler) = 0;

  // send() sends a request to the remote endpoint.
  // 'requestTypeInfo' is the type info of the request data structure.
  // 'requestTypeInfo' is the type info of the response data structure.
  // 'request' is a pointer to the request data structure.
  // 'responseHandler' is the handler function for the response.
  virtual bool send(const dap::TypeInfo* requestTypeInfo,
                    const dap::TypeInfo* responseTypeInfo,
                    const void* request,
                    const GenericResponseHandler& responseHandler) = 0;

  // send() sends an event to the remote endpoint.
  // 'eventTypeInfo' is the type info for the event data structure.
  // 'event' is a pointer to the event data structure.
  virtual bool send(const TypeInfo* eventTypeInfo, const void* event) = 0;
};

template <typename F, typename RequestType>
Session::IsRequestHandlerWithoutCallback<F> Session::registerHandler(
    F&& handler) {
  using ResponseType = typename RequestType::Response;
  const TypeInfo* typeinfo = TypeOf<RequestType>::type();
  registerHandler(typeinfo,
                  [handler](const void* args,
                            const RequestHandlerSuccessCallback& onSuccess,
                            const RequestHandlerErrorCallback& onError) {
                    ResponseOrError<ResponseType> res =
                        handler(*reinterpret_cast<const RequestType*>(args));
                    if (res.error) {
                      onError(TypeOf<ResponseType>::type(), res.error);
                    } else {
                      onSuccess(TypeOf<ResponseType>::type(), &res.response);
                    }
                  });
}

template <typename F, typename RequestType, typename ResponseType>
Session::IsRequestHandlerWithCallback<F, ResponseType> Session::registerHandler(
    F&& handler) {
  using CallbackType = ParamType<F, 1>;
  registerHandler(
      TypeOf<RequestType>::type(),
      [handler](const void* args,
                const RequestHandlerSuccessCallback& onSuccess,
                const RequestHandlerErrorCallback&) {
        CallbackType responseCallback = [onSuccess](const ResponseType& res) {
          onSuccess(TypeOf<ResponseType>::type(), &res);
        };
        handler(*reinterpret_cast<const RequestType*>(args), responseCallback);
      });
}

template <typename F, typename RequestType, typename ResponseType>
Session::IsRequestHandlerWithCallback<F, ResponseOrError<ResponseType>>
Session::registerHandler(F&& handler) {
  using CallbackType = ParamType<F, 1>;
  registerHandler(
      TypeOf<RequestType>::type(),
      [handler](const void* args,
                const RequestHandlerSuccessCallback& onSuccess,
                const RequestHandlerErrorCallback& onError) {
        CallbackType responseCallback =
            [onError, onSuccess](const ResponseOrError<ResponseType>& res) {
              if (res.error) {
                onError(TypeOf<ResponseType>::type(), res.error);
              } else {
                onSuccess(TypeOf<ResponseType>::type(), &res.response);
              }
            };
        handler(*reinterpret_cast<const RequestType*>(args), responseCallback);
      });
}

template <typename F, typename T>
Session::IsEvent<T> Session::registerHandler(F&& handler) {
  auto cb = [handler](const void* args) {
    handler(*reinterpret_cast<const T*>(args));
  };
  const TypeInfo* typeinfo = TypeOf<T>::type();
  registerHandler(typeinfo, cb);
}

template <typename F, typename T>
void Session::registerSentHandler(F&& handler) {
  auto cb = [handler](const void* response, const Error* error) {
    if (error != nullptr) {
      handler(ResponseOrError<T>(*error));
    } else {
      handler(ResponseOrError<T>(*reinterpret_cast<const T*>(response)));
    }
  };
  const TypeInfo* typeinfo = TypeOf<T>::type();
  registerHandler(typeinfo, cb);
}

template <typename T, typename>
future<ResponseOrError<typename T::Response>> Session::send(const T& request) {
  using Response = typename T::Response;
  promise<ResponseOrError<Response>> promise;
  auto sent = send(TypeOf<T>::type(), TypeOf<Response>::type(), &request,
                   [=](const void* result, const Error* error) {
                     if (error != nullptr) {
                       promise.set_value(ResponseOrError<Response>(*error));
                     } else {
                       promise.set_value(ResponseOrError<Response>(
                           *reinterpret_cast<const Response*>(result)));
                     }
                   });
  if (!sent) {
    promise.set_value(Error("Failed to send request"));
  }
  return promise.get_future();
}

template <typename T, typename>
void Session::send(const T& event) {
  const TypeInfo* typeinfo = TypeOf<T>::type();
  send(typeinfo, &event);
}

void Session::connect(const std::shared_ptr<ReaderWriter>& rw) {
  connect(rw, rw);
}

void Session::bind(const std::shared_ptr<dap::Reader>& r,
                   const std::shared_ptr<dap::Writer>& w,
                   const ClosedHandler& onClose = {}) {
  connect(r, w);
  startProcessingMessages(onClose);
}

void Session::bind(const std::shared_ptr<ReaderWriter>& rw,
                   const ClosedHandler& onClose = {}) {
  bind(rw, rw, onClose);
}

}  // namespace dap

#endif  // dap_session_h
