//
//
// Copyright 2015 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 GRPC_TEST_CPP_QPS_SERVER_H
#define GRPC_TEST_CPP_QPS_SERVER_H

#include <vector>

#include <grpc/support/cpu.h>
#include <grpc/support/log.h>
#include <grpcpp/channel.h>
#include <grpcpp/resource_quota.h>
#include <grpcpp/security/server_credentials.h>
#include <grpcpp/server_builder.h>

#include "src/core/lib/gprpp/crash.h"
#include "src/proto/grpc/testing/control.pb.h"
#include "src/proto/grpc/testing/messages.pb.h"
#include "test/core/end2end/data/ssl_test_data.h"
#include "test/core/util/port.h"
#include "test/cpp/qps/usage_timer.h"
#include "test/cpp/util/test_credentials_provider.h"

namespace grpc {
namespace testing {

class Server {
 public:
  explicit Server(const ServerConfig& config)
      : timer_(new UsageTimer), last_reset_poll_count_(0) {
    cores_ = gpr_cpu_num_cores();
    if (config.port()) {  // positive for a fixed port, negative for inproc
      port_ = config.port();
    } else {  // zero for dynamic port
      port_ = grpc_pick_unused_port_or_die();
    }
  }
  virtual ~Server() {}

  ServerStats Mark(bool reset) {
    UsageTimer::Result timer_result;
    int cur_poll_count = GetPollCount();
    int poll_count = cur_poll_count - last_reset_poll_count_;
    if (reset) {
      std::unique_ptr<UsageTimer> timer(new UsageTimer);
      timer.swap(timer_);
      timer_result = timer->Mark();
      last_reset_poll_count_ = cur_poll_count;
    } else {
      timer_result = timer_->Mark();
    }

    ServerStats stats;
    stats.set_time_elapsed(timer_result.wall);
    stats.set_time_system(timer_result.system);
    stats.set_time_user(timer_result.user);
    stats.set_total_cpu_time(timer_result.total_cpu_time);
    stats.set_idle_cpu_time(timer_result.idle_cpu_time);
    stats.set_cq_poll_count(poll_count);
    return stats;
  }

  static bool SetPayload(PayloadType type, int size, Payload* payload) {
    // TODO(yangg): Support UNCOMPRESSABLE payload.
    if (type != PayloadType::COMPRESSABLE) {
      return false;
    }
    payload->set_type(type);
    // Don't waste time creating a new payload of identical size.
    if (payload->body().length() != static_cast<size_t>(size)) {
      std::unique_ptr<char[]> body(new char[size]());
      payload->set_body(body.get(), size);
    }
    return true;
  }

  int port() const { return port_; }
  int cores() const { return cores_; }
  static std::shared_ptr<ServerCredentials> CreateServerCredentials(
      const ServerConfig& config) {
    if (config.has_security_params()) {
      std::string type;
      if (config.security_params().cred_type().empty()) {
        type = kTlsCredentialsType;
      } else {
        type = config.security_params().cred_type();
      }

      return GetCredentialsProvider()->GetServerCredentials(type);
    } else {
      return InsecureServerCredentials();
    }
  }

  virtual int GetPollCount() {
    // For sync server.
    return 0;
  }

  virtual std::shared_ptr<Channel> InProcessChannel(
      const ChannelArguments& args) = 0;

 protected:
  static void ApplyConfigToBuilder(const ServerConfig& config,
                                   ServerBuilder* builder) {
    if (config.resource_quota_size() > 0) {
      builder->SetResourceQuota(ResourceQuota("AsyncQpsServerTest")
                                    .Resize(config.resource_quota_size()));
    }
    for (const auto& channel_arg : config.channel_args()) {
      switch (channel_arg.value_case()) {
        case ChannelArg::kStrValue:
          builder->AddChannelArgument(channel_arg.name(),
                                      channel_arg.str_value());
          break;
        case ChannelArg::kIntValue:
          builder->AddChannelArgument(channel_arg.name(),
                                      channel_arg.int_value());
          break;
        case ChannelArg::VALUE_NOT_SET:
          gpr_log(GPR_ERROR, "Channel arg '%s' does not have a value",
                  channel_arg.name().c_str());
          break;
      }
    }
  }

 private:
  int port_;
  int cores_;
  std::unique_ptr<UsageTimer> timer_;
  int last_reset_poll_count_;
};

std::unique_ptr<Server> CreateSynchronousServer(const ServerConfig& config);
std::unique_ptr<Server> CreateAsyncServer(const ServerConfig& config);
std::unique_ptr<Server> CreateAsyncGenericServer(const ServerConfig& config);
std::unique_ptr<Server> CreateCallbackServer(const ServerConfig& config);

}  // namespace testing
}  // namespace grpc

#endif  // GRPC_TEST_CPP_QPS_SERVER_H
