/*
 *
 * Copyright 2016 gRPC 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
 *
 *     http://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 GRPCPP_IMPL_CODEGEN_CHANNEL_INTERFACE_H
#define GRPCPP_IMPL_CODEGEN_CHANNEL_INTERFACE_H

#include <grpc/impl/codegen/connectivity_state.h>
#include <grpcpp/impl/codegen/call.h>
#include <grpcpp/impl/codegen/status.h>
#include <grpcpp/impl/codegen/time.h>

namespace grpc {
template <class R>
class ClientReader;
template <class W>
class ClientWriter;
template <class W, class R>
class ClientReaderWriter;
namespace internal {
template <class InputMessage, class OutputMessage>
class CallbackUnaryCallImpl;
template <class R>
class ClientAsyncReaderFactory;
template <class W>
class ClientAsyncWriterFactory;
template <class W, class R>
class ClientAsyncReaderWriterFactory;
template <class R>
class ClientAsyncResponseReaderFactory;
template <class W, class R>
class ClientCallbackReaderWriterFactory;
template <class R>
class ClientCallbackReaderFactory;
template <class W>
class ClientCallbackWriterFactory;
class ClientCallbackUnaryFactory;
}  // namespace internal

class ChannelInterface;
class ClientContext;
class CompletionQueue;

namespace experimental {
class DelegatingChannel;
}

namespace internal {
class Call;
class CallOpSetInterface;
class RpcMethod;
class InterceptedChannel;
template <class InputMessage, class OutputMessage>
class BlockingUnaryCallImpl;
}  // namespace internal

/// Codegen interface for \a grpc::Channel.
class ChannelInterface {
 public:
  virtual ~ChannelInterface() {}
  /// Get the current channel state. If the channel is in IDLE and
  /// \a try_to_connect is set to true, try to connect.
  virtual grpc_connectivity_state GetState(bool try_to_connect) = 0;

  /// Return the \a tag on \a cq when the channel state is changed or \a
  /// deadline expires. \a GetState needs to called to get the current state.
  template <typename T>
  void NotifyOnStateChange(grpc_connectivity_state last_observed, T deadline,
                           ::grpc::CompletionQueue* cq, void* tag) {
    TimePoint<T> deadline_tp(deadline);
    NotifyOnStateChangeImpl(last_observed, deadline_tp.raw_time(), cq, tag);
  }

  /// Blocking wait for channel state change or \a deadline expiration.
  /// \a GetState needs to called to get the current state.
  template <typename T>
  bool WaitForStateChange(grpc_connectivity_state last_observed, T deadline) {
    TimePoint<T> deadline_tp(deadline);
    return WaitForStateChangeImpl(last_observed, deadline_tp.raw_time());
  }

  /// Wait for this channel to be connected
  template <typename T>
  bool WaitForConnected(T deadline) {
    grpc_connectivity_state state;
    while ((state = GetState(true)) != GRPC_CHANNEL_READY) {
      if (!WaitForStateChange(state, deadline)) return false;
    }
    return true;
  }

 private:
  template <class R>
  friend class ::grpc::ClientReader;
  template <class W>
  friend class ::grpc::ClientWriter;
  template <class W, class R>
  friend class ::grpc::ClientReaderWriter;
  template <class R>
  friend class ::grpc::internal::ClientAsyncReaderFactory;
  template <class W>
  friend class ::grpc::internal::ClientAsyncWriterFactory;
  template <class W, class R>
  friend class ::grpc::internal::ClientAsyncReaderWriterFactory;
  template <class R>
  friend class ::grpc::internal::ClientAsyncResponseReaderFactory;
  template <class W, class R>
  friend class ::grpc::internal::ClientCallbackReaderWriterFactory;
  template <class R>
  friend class ::grpc::internal::ClientCallbackReaderFactory;
  template <class W>
  friend class ::grpc::internal::ClientCallbackWriterFactory;
  friend class ::grpc::internal::ClientCallbackUnaryFactory;
  template <class InputMessage, class OutputMessage>
  friend class ::grpc::internal::BlockingUnaryCallImpl;
  template <class InputMessage, class OutputMessage>
  friend class ::grpc::internal::CallbackUnaryCallImpl;
  friend class ::grpc::internal::RpcMethod;
  friend class ::grpc::experimental::DelegatingChannel;
  friend class ::grpc::internal::InterceptedChannel;
  virtual internal::Call CreateCall(const internal::RpcMethod& method,
                                    ::grpc::ClientContext* context,
                                    ::grpc::CompletionQueue* cq) = 0;
  virtual void PerformOpsOnCall(internal::CallOpSetInterface* ops,
                                internal::Call* call) = 0;
  virtual void* RegisterMethod(const char* method) = 0;
  virtual void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
                                       gpr_timespec deadline,
                                       ::grpc::CompletionQueue* cq,
                                       void* tag) = 0;
  virtual bool WaitForStateChangeImpl(grpc_connectivity_state last_observed,
                                      gpr_timespec deadline) = 0;

  // EXPERIMENTAL
  // This is needed to keep codegen_test_minimal happy. InterceptedChannel needs
  // to make use of this but can't directly call Channel's implementation
  // because of the test.
  // Returns an empty Call object (rather than being pure) since this is a new
  // method and adding a new pure method to an interface would be a breaking
  // change (even though this is private and non-API)
  virtual internal::Call CreateCallInternal(
      const internal::RpcMethod& /*method*/, ::grpc::ClientContext* /*context*/,
      ::grpc::CompletionQueue* /*cq*/, size_t /*interceptor_pos*/) {
    return internal::Call();
  }

  // EXPERIMENTAL
  // A method to get the callbackable completion queue associated with this
  // channel. If the return value is nullptr, this channel doesn't support
  // callback operations.
  // TODO(vjpai): Consider a better default like using a global CQ
  // Returns nullptr (rather than being pure) since this is a post-1.0 method
  // and adding a new pure method to an interface would be a breaking change
  // (even though this is private and non-API)
  virtual ::grpc::CompletionQueue* CallbackCQ() { return nullptr; }
};
}  // namespace grpc

#endif  // GRPCPP_IMPL_CODEGEN_CHANNEL_INTERFACE_H
