/*
 *
 * Copyright 2018 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.
 *
 */

#include <grpc/support/port_platform.h>

#include "src/core/ext/filters/client_channel/client_channel.h"
#include "src/core/ext/filters/client_channel/client_channel_channelz.h"
#include "src/core/lib/channel/channelz_registry.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/connectivity_state.h"

#include <grpc/support/string_util.h>

namespace grpc_core {
namespace channelz {
namespace {

void* client_channel_channelz_copy(void* p) { return p; }

void client_channel_channelz_destroy(void* p) {}

int client_channel_channelz_cmp(void* a, void* b) { return GPR_ICMP(a, b); }

}  // namespace

static const grpc_arg_pointer_vtable client_channel_channelz_vtable = {
    client_channel_channelz_copy, client_channel_channelz_destroy,
    client_channel_channelz_cmp};

ClientChannelNode::ClientChannelNode(grpc_channel* channel,
                                     size_t channel_tracer_max_nodes,
                                     bool is_top_level_channel)
    : ChannelNode(channel, channel_tracer_max_nodes, is_top_level_channel) {
  client_channel_ =
      grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel));
  grpc_client_channel_set_channelz_node(client_channel_, this);
  GPR_ASSERT(client_channel_->filter == &grpc_client_channel_filter);
}

void ClientChannelNode::PopulateConnectivityState(grpc_json* json) {
  grpc_connectivity_state state;
  if (ChannelIsDestroyed()) {
    state = GRPC_CHANNEL_SHUTDOWN;
  } else {
    state =
        grpc_client_channel_check_connectivity_state(client_channel_, false);
  }
  json = grpc_json_create_child(nullptr, json, "state", nullptr,
                                GRPC_JSON_OBJECT, false);
  grpc_json_create_child(nullptr, json, "state",
                         grpc_connectivity_state_name(state), GRPC_JSON_STRING,
                         false);
}

void ClientChannelNode::PopulateChildRefs(grpc_json* json) {
  ChildRefsList child_subchannels;
  ChildRefsList child_channels;
  grpc_json* json_iterator = nullptr;
  grpc_client_channel_populate_child_refs(client_channel_, &child_subchannels,
                                          &child_channels);
  if (!child_subchannels.empty()) {
    grpc_json* array_parent = grpc_json_create_child(
        nullptr, json, "subchannelRef", nullptr, GRPC_JSON_ARRAY, false);
    for (size_t i = 0; i < child_subchannels.size(); ++i) {
      json_iterator =
          grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr,
                                 GRPC_JSON_OBJECT, false);
      grpc_json_add_number_string_child(json_iterator, nullptr, "subchannelId",
                                        child_subchannels[i]);
    }
  }
  if (!child_channels.empty()) {
    grpc_json* array_parent = grpc_json_create_child(
        nullptr, json, "channelRef", nullptr, GRPC_JSON_ARRAY, false);
    json_iterator = nullptr;
    for (size_t i = 0; i < child_channels.size(); ++i) {
      json_iterator =
          grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr,
                                 GRPC_JSON_OBJECT, false);
      grpc_json_add_number_string_child(json_iterator, nullptr, "channelId",
                                        child_channels[i]);
    }
  }
}

grpc_arg ClientChannelNode::CreateChannelArg() {
  return grpc_channel_arg_pointer_create(
      const_cast<char*>(GRPC_ARG_CHANNELZ_CHANNEL_NODE_CREATION_FUNC),
      reinterpret_cast<void*>(MakeClientChannelNode),
      &client_channel_channelz_vtable);
}

RefCountedPtr<ChannelNode> ClientChannelNode::MakeClientChannelNode(
    grpc_channel* channel, size_t channel_tracer_max_nodes,
    bool is_top_level_channel) {
  return MakeRefCounted<ClientChannelNode>(channel, channel_tracer_max_nodes,
                                           is_top_level_channel);
}

SubchannelNode::SubchannelNode(grpc_subchannel* subchannel,
                               size_t channel_tracer_max_nodes)
    : BaseNode(EntityType::kSubchannel),
      subchannel_(subchannel),
      target_(
          UniquePtr<char>(gpr_strdup(grpc_subchannel_get_target(subchannel_)))),
      trace_(channel_tracer_max_nodes) {}

SubchannelNode::~SubchannelNode() {}

void SubchannelNode::PopulateConnectivityState(grpc_json* json) {
  grpc_connectivity_state state;
  if (subchannel_ == nullptr) {
    state = GRPC_CHANNEL_SHUTDOWN;
  } else {
    state = grpc_subchannel_check_connectivity(
        subchannel_, nullptr, true /* inhibit_health_checking */);
  }
  json = grpc_json_create_child(nullptr, json, "state", nullptr,
                                GRPC_JSON_OBJECT, false);
  grpc_json_create_child(nullptr, json, "state",
                         grpc_connectivity_state_name(state), GRPC_JSON_STRING,
                         false);
}

grpc_json* SubchannelNode::RenderJson() {
  grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT);
  grpc_json* json = top_level_json;
  grpc_json* json_iterator = nullptr;
  json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr,
                                         GRPC_JSON_OBJECT, false);
  json = json_iterator;
  json_iterator = nullptr;
  json_iterator = grpc_json_add_number_string_child(json, json_iterator,
                                                    "subchannelId", uuid());
  // reset json iterators to top level object
  json = top_level_json;
  json_iterator = nullptr;
  // create and fill the data child.
  grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr,
                                           GRPC_JSON_OBJECT, false);
  json = data;
  json_iterator = nullptr;
  PopulateConnectivityState(json);
  GPR_ASSERT(target_.get() != nullptr);
  grpc_json_create_child(nullptr, json, "target", target_.get(),
                         GRPC_JSON_STRING, false);
  // fill in the channel trace if applicable
  grpc_json* trace_json = trace_.RenderJson();
  if (trace_json != nullptr) {
    trace_json->key = "trace";  // this object is named trace in channelz.proto
    grpc_json_link_child(json, trace_json, nullptr);
  }
  // ask CallCountingHelper to populate trace and call count data.
  call_counter_.PopulateCallCounts(json);
  json = top_level_json;
  // populate the child socket.
  intptr_t socket_uuid = grpc_subchannel_get_child_socket_uuid(subchannel_);
  if (socket_uuid != 0) {
    grpc_json* array_parent = grpc_json_create_child(
        nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false);
    json_iterator = grpc_json_create_child(json_iterator, array_parent, nullptr,
                                           nullptr, GRPC_JSON_OBJECT, false);
    grpc_json_add_number_string_child(json_iterator, nullptr, "socketId",
                                      socket_uuid);
  }
  return top_level_json;
}

}  // namespace channelz
}  // namespace grpc_core
