// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/lib/fidl_codec/proto_value.h"

#include "src/lib/fidl_codec/logger.h"
#include "src/lib/fidl_codec/proto/value.pb.h"
#include "src/lib/fidl_codec/visitor.h"
#include "src/lib/fidl_codec/wire_object.h"
#include "src/lib/fidl_codec/wire_types.h"

namespace fidl_codec {

void ProtoEncodeStruct(proto::Struct* dst, const fidl_codec::StructValue* node) {
  for (const auto& field : node->fields()) {
    auto proto_field = dst->add_fields();
    proto_field->set_name(field.first->name());
    proto_field->set_id(field.first->id());

    auto value = proto_field->mutable_value();
    ProtoVisitor visitor(value);
    field.second->Visit(&visitor, nullptr);
  }
}

void ProtoVisitor::VisitNullValue(const fidl_codec::NullValue* node,
                                  const fidl_codec::Type* for_type) {
  dst_->set_null_value(true);
}

void ProtoVisitor::VisitRawValue(const fidl_codec::RawValue* node,
                                 const fidl_codec::Type* for_type) {
  dst_->set_raw_value(node->data().data(), node->data().size());
}

void ProtoVisitor::VisitBoolValue(const fidl_codec::BoolValue* node,
                                  const fidl_codec::Type* for_type) {
  dst_->set_bool_value(node->value());
}

void ProtoVisitor::VisitIntegerValue(const fidl_codec::IntegerValue* node,
                                     const fidl_codec::Type* for_type) {
  proto::Integer* integer = dst_->mutable_integer_value();
  integer->set_absolute_value(node->absolute_value());
  integer->set_negative(node->negative());
}

void ProtoVisitor::VisitDoubleValue(const fidl_codec::DoubleValue* node,
                                    const fidl_codec::Type* for_type) {
  dst_->set_double_value(node->value());
}

void ProtoVisitor::VisitStringValue(const fidl_codec::StringValue* node,
                                    const fidl_codec::Type* for_type) {
  dst_->set_string_value(node->string());
}

void ProtoVisitor::VisitHandleValue(const fidl_codec::HandleValue* node,
                                    const fidl_codec::Type* for_type) {
  proto::HandleInfo* handle_info = dst_->mutable_handle_value();
  handle_info->set_handle(node->handle().handle);
  handle_info->set_type(node->handle().type);
  handle_info->set_rights(node->handle().rights);
}

void ProtoVisitor::VisitUnionValue(const fidl_codec::UnionValue* node,
                                   const fidl_codec::Type* for_type) {
  proto::Union* union_value = dst_->mutable_union_value();
  union_value->set_member(node->member().name());
  ProtoVisitor visitor(union_value->mutable_value());
  node->value()->Visit(&visitor, nullptr);
}

void ProtoVisitor::VisitStructValue(const fidl_codec::StructValue* node,
                                    const fidl_codec::Type* for_type) {
  ProtoEncodeStruct(dst_->mutable_struct_value(), node);
}

void ProtoVisitor::VisitVectorValue(const fidl_codec::VectorValue* node,
                                    const fidl_codec::Type* for_type) {
  proto::Vector* vector_value = dst_->mutable_vector_value();
  for (const auto& value : node->values()) {
    ProtoVisitor visitor(vector_value->add_value());
    value->Visit(&visitor, nullptr);
  }
}

void ProtoVisitor::VisitTableValue(const fidl_codec::TableValue* node,
                                   const fidl_codec::Type* for_type) {
  proto::Table* table_value = dst_->mutable_table_value();
  for (const auto& member : node->members()) {
    proto::Value value;
    ProtoVisitor visitor(&value);
    member.second->Visit(&visitor, nullptr);
    table_value->mutable_members()->insert(google::protobuf::MapPair(member.first->name(), value));
  }
}

void ProtoVisitor::VisitFidlMessageValue(const fidl_codec::FidlMessageValue* node,
                                         const fidl_codec::Type* for_type) {
  proto::FidlMessage* fidl_message = dst_->mutable_fidl_message_value();
  fidl_message->set_txid(node->txid());
  fidl_message->set_ordinal(node->ordinal());
  fidl_message->set_global_errors(node->global_errors());
  fidl_message->set_epitaph_error(node->epitaph_error());
  fidl_message->set_received(node->received());
  fidl_message->set_is_request(node->is_request());
  fidl_message->set_unknown_direction(node->unknown_direction());
  if (node->method() != nullptr) {
    fidl_message->set_interface(node->method()->enclosing_interface().name());
    fidl_message->set_method(node->method()->name());
  }
  fidl_message->set_raw_bytes(node->bytes().data(), node->bytes().size());
  for (const auto& handle : node->handles()) {
    proto::HandleInfo* handle_info = fidl_message->add_handle();
    handle_info->set_handle(handle.handle);
    handle_info->set_type(handle.type);
    handle_info->set_rights(handle.rights);
  }
  if (node->decoded_request() != nullptr) {
    fidl_message->set_has_request(true);
    ProtoEncodeStruct(fidl_message->mutable_decoded_request(), node->decoded_request());
  }
  fidl_message->set_request_errors(node->request_errors());
  if (node->decoded_response() != nullptr) {
    fidl_message->set_has_response(true);
    ProtoEncodeStruct(fidl_message->mutable_decoded_response(), node->decoded_response());
  }
  fidl_message->set_response_errors(node->response_errors());
}

std::unique_ptr<StructValue> DecodeStruct(LibraryLoader* loader, const proto::Struct& proto_struct,
                                          const Struct& struct_definition) {
  bool ok = true;
  auto struct_value = std::make_unique<fidl_codec::StructValue>(struct_definition);
  for (const auto& proto_field : proto_struct.fields()) {
    const fidl_codec::StructMember* member =
        struct_definition.SearchMember(proto_field.name(), proto_field.id());
    if (member == nullptr) {
      FX_LOGS_OR_CAPTURE(ERROR) << "Member " << proto_field.name() << ":" << proto_field.id()
                                << " not found in " << struct_definition.name() << '.';
      ok = false;
    } else {
      std::unique_ptr<fidl_codec::Value> value =
          DecodeValue(loader, proto_field.value(), member->type());
      if (value == nullptr) {
        ok = false;
      } else {
        struct_value->AddField(member, std::move(value));
      }
    }
  }
  if (!ok) {
    return nullptr;
  }
  return struct_value;
}

std::unique_ptr<Value> DecodeValue(LibraryLoader* loader, const proto::Value& proto_value,
                                   const Type* type) {
  switch (proto_value.Kind_case()) {
    case proto::Value::kNullValue:
      return std::make_unique<fidl_codec::NullValue>();
    case proto::Value::kRawValue:
      return std::make_unique<fidl_codec::RawValue>(
          reinterpret_cast<const uint8_t*>(proto_value.raw_value().data()),
          proto_value.raw_value().size());
    case proto::Value::kBoolValue:
      return std::make_unique<fidl_codec::BoolValue>(proto_value.bool_value());
    case proto::Value::kIntegerValue:
      return std::make_unique<fidl_codec::IntegerValue>(
          proto_value.integer_value().absolute_value(), proto_value.integer_value().negative());
    case proto::Value::kDoubleValue:
      return std::make_unique<fidl_codec::DoubleValue>(proto_value.double_value());
    case proto::Value::kStringValue:
      return std::make_unique<fidl_codec::StringValue>(proto_value.string_value());
    case proto::Value::kHandleValue: {
      const proto::HandleInfo& proto_handle_info = proto_value.handle_value();
      zx_handle_info handle_info;
      handle_info.handle = proto_handle_info.handle();
      handle_info.type = proto_handle_info.type();
      handle_info.rights = proto_handle_info.rights();
      return std::make_unique<fidl_codec::HandleValue>(handle_info);
    }
    case proto::Value::kUnionValue: {
      auto union_type = type->AsUnionType();
      if (union_type == nullptr) {
        FX_LOGS_OR_CAPTURE(ERROR) << "Type of union value should be union.";
        return nullptr;
      }
      fidl_codec::UnionMember* member =
          union_type->union_definition().SearchMember(proto_value.union_value().member());
      if (member == nullptr) {
        FX_LOGS_OR_CAPTURE(ERROR) << "Member " << proto_value.union_value().member()
                                  << " not found in union " << union_type->union_definition().name()
                                  << '.';
        return nullptr;
      }
      std::unique_ptr<fidl_codec::Value> union_value =
          DecodeValue(loader, proto_value.union_value().value(), member->type());
      if (union_value == nullptr) {
        return nullptr;
      }
      return std::make_unique<fidl_codec::UnionValue>(*member, std::move(union_value));
    }
    case proto::Value::kStructValue: {
      auto struct_type = type->AsStructType();
      if (struct_type == nullptr) {
        FX_LOGS_OR_CAPTURE(ERROR) << "Type of struct value should be struct.";
        return nullptr;
      }
      return DecodeStruct(loader, proto_value.struct_value(), struct_type->struct_definition());
    }
    case proto::Value::kVectorValue: {
      const fidl_codec::Type* component_type = type->GetComponentType();
      if (component_type == nullptr) {
        FX_LOGS_OR_CAPTURE(ERROR) << "Type of vector should be array or vector.";
        return nullptr;
      }
      bool ok = true;
      auto vector_value = std::make_unique<fidl_codec::VectorValue>();
      const proto::Vector& proto_vector_value = proto_value.vector_value();
      for (int index = 0; index < proto_vector_value.value_size(); ++index) {
        std::unique_ptr<fidl_codec::Value> value =
            DecodeValue(loader, proto_vector_value.value(index), component_type);
        if (value == nullptr) {
          ok = false;
        } else {
          vector_value->AddValue(std::move(value));
        }
      }
      if (!ok) {
        return nullptr;
      }
      return vector_value;
    }
    case proto::Value::kTableValue: {
      auto table_type = type->AsTableType();
      if (table_type == nullptr) {
        FX_LOGS_OR_CAPTURE(ERROR) << "Type of table value should be table.";
        return nullptr;
      }
      bool ok = true;
      auto table_value = std::make_unique<fidl_codec::TableValue>(table_type->table_definition());
      for (const auto& proto_member : proto_value.table_value().members()) {
        const fidl_codec::TableMember* member =
            table_type->table_definition().GetMember(proto_member.first);
        if (member == nullptr) {
          FX_LOGS_OR_CAPTURE(ERROR) << "Member " << proto_member.first << " not found in "
                                    << table_type->table_definition().name() << '.';
          ok = false;
        } else {
          std::unique_ptr<fidl_codec::Value> value =
              DecodeValue(loader, proto_member.second, member->type());
          if (value == nullptr) {
            ok = false;
          } else {
            table_value->AddMember(member, std::move(value));
          }
        }
      }
      if (!ok) {
        return nullptr;
      }
      return table_value;
    }
    case proto::Value::kFidlMessageValue: {
      const proto::FidlMessage& proto_message = proto_value.fidl_message_value();
      const fidl_codec::InterfaceMethod* method = nullptr;
      // We need to check loader because some tests have a null library loader.
      if (loader != nullptr) {
        const std::vector<const fidl_codec::InterfaceMethod*>* methods =
            loader->GetByOrdinal(proto_message.ordinal());
        if ((methods != nullptr) && !methods->empty()) {
          method = (*methods)[0];
        }
      }
      auto message = std::make_unique<fidl_codec::FidlMessageValue>(
          proto_message.txid(), proto_message.ordinal(), proto_message.global_errors(),
          proto_message.epitaph_error(), proto_message.received(), proto_message.is_request(),
          proto_message.unknown_direction(), method,
          reinterpret_cast<const uint8_t*>(proto_message.raw_bytes().data()),
          proto_message.raw_bytes().size(), proto_message.request_errors(),
          proto_message.response_errors());
      for (int index = 0; index < proto_message.handle_size(); ++index) {
        const proto::HandleInfo proto_handle_info = proto_message.handle(index);
        zx_handle_info handle_info;
        handle_info.handle = proto_handle_info.handle();
        handle_info.type = proto_handle_info.type();
        handle_info.rights = proto_handle_info.rights();
        message->add_handle(handle_info);
      }
      if (method != nullptr) {
        // We can have a null method if we replay a file with a different state (for example, we
        // don't have all the json we had when the event has been saved).
        bool ok = true;
        if (proto_message.has_request()) {
          if (method->request() == nullptr) {
            FX_LOGS_OR_CAPTURE(ERROR)
                << "Request without request defined in " << method->name() << '.';
            ok = false;
          } else {
            message->set_decoded_request(
                DecodeStruct(loader, proto_message.decoded_request(), *method->request()));
          }
        }
        if (proto_message.has_response()) {
          if (method->response() == nullptr) {
            FX_LOGS_OR_CAPTURE(ERROR)
                << "Response without response defined in " << method->name() << '.';
            ok = false;
          } else {
            message->set_decoded_response(
                DecodeStruct(loader, proto_message.decoded_response(), *method->response()));
          }
        }
        if (!ok) {
          return nullptr;
        }
      }
      return message;
    }
    default:
      FX_LOGS_OR_CAPTURE(ERROR) << "Unknown value.";
      return nullptr;
  }
}

}  // namespace fidl_codec
