// Copyright 2013 The Flutter 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 "flutter/shell/platform/common/cpp/json_method_codec.h"

#include "flutter/shell/platform/common/cpp/json_message_codec.h"

namespace flutter {

namespace {

// Keys used in MethodCall encoding.
constexpr char kMessageMethodKey[] = "method";
constexpr char kMessageArgumentsKey[] = "args";

// Returns a new document containing only |element|, which must be an element
// in |document|. This is a move rather than a copy, so it is efficient but
// destructive to the data in |document|.
std::unique_ptr<rapidjson::Document> ExtractElement(
    rapidjson::Document* document,
    rapidjson::Value* subtree) {
  auto extracted = std::make_unique<rapidjson::Document>();
  // Pull the subtree up to the root of the document.
  document->Swap(*subtree);
  // Swap the entire document into |extracted|. Unlike the swap above this moves
  // the allocator ownership, so the data won't be deleted when |document| is
  // destroyed.
  extracted->Swap(*document);
  return extracted;
}

}  // namespace

// static
const JsonMethodCodec& JsonMethodCodec::GetInstance() {
  static JsonMethodCodec sInstance;
  return sInstance;
}

std::unique_ptr<MethodCall<rapidjson::Document>>
JsonMethodCodec::DecodeMethodCallInternal(const uint8_t* message,
                                          size_t message_size) const {
  std::unique_ptr<rapidjson::Document> json_message =
      JsonMessageCodec::GetInstance().DecodeMessage(message, message_size);
  if (!json_message) {
    return nullptr;
  }

  auto method_name_iter = json_message->FindMember(kMessageMethodKey);
  if (method_name_iter == json_message->MemberEnd()) {
    return nullptr;
  }
  if (!method_name_iter->value.IsString()) {
    return nullptr;
  }
  std::string method_name(method_name_iter->value.GetString());
  auto arguments_iter = json_message->FindMember(kMessageArgumentsKey);
  std::unique_ptr<rapidjson::Document> arguments;
  if (arguments_iter != json_message->MemberEnd()) {
    arguments = ExtractElement(json_message.get(), &(arguments_iter->value));
  }
  return std::make_unique<MethodCall<rapidjson::Document>>(
      method_name, std::move(arguments));
}

std::unique_ptr<std::vector<uint8_t>> JsonMethodCodec::EncodeMethodCallInternal(
    const MethodCall<rapidjson::Document>& method_call) const {
  // TODO: Consider revisiting the codec APIs to avoid the need to copy
  // everything when doing encoding (e.g., by having a version that takes
  // owership of the object to encode, so that it can be moved instead).
  rapidjson::Document message(rapidjson::kObjectType);
  auto& allocator = message.GetAllocator();
  rapidjson::Value name(method_call.method_name(), allocator);
  rapidjson::Value arguments;
  if (method_call.arguments()) {
    arguments.CopyFrom(*method_call.arguments(), allocator);
  }
  message.AddMember(kMessageMethodKey, name, allocator);
  message.AddMember(kMessageArgumentsKey, arguments, allocator);

  return JsonMessageCodec::GetInstance().EncodeMessage(message);
}

std::unique_ptr<std::vector<uint8_t>>
JsonMethodCodec::EncodeSuccessEnvelopeInternal(
    const rapidjson::Document* result) const {
  rapidjson::Document envelope;
  envelope.SetArray();
  rapidjson::Value result_value;
  if (result) {
    result_value.CopyFrom(*result, envelope.GetAllocator());
  }
  envelope.PushBack(result_value, envelope.GetAllocator());

  return JsonMessageCodec::GetInstance().EncodeMessage(envelope);
}

std::unique_ptr<std::vector<uint8_t>>
JsonMethodCodec::EncodeErrorEnvelopeInternal(
    const std::string& error_code,
    const std::string& error_message,
    const rapidjson::Document* error_details) const {
  rapidjson::Document envelope(rapidjson::kArrayType);
  auto& allocator = envelope.GetAllocator();
  envelope.PushBack(rapidjson::Value(error_code, allocator), allocator);
  envelope.PushBack(rapidjson::Value(error_message, allocator), allocator);
  rapidjson::Value details_value;
  if (error_details) {
    details_value.CopyFrom(*error_details, allocator);
  }
  envelope.PushBack(details_value, allocator);

  return JsonMessageCodec::GetInstance().EncodeMessage(envelope);
}

bool JsonMethodCodec::DecodeAndProcessResponseEnvelopeInternal(
    const uint8_t* response,
    size_t response_size,
    MethodResult<rapidjson::Document>* result) const {
  std::unique_ptr<rapidjson::Document> json_response =
      JsonMessageCodec::GetInstance().DecodeMessage(response, response_size);
  if (!json_response) {
    return false;
  }
  if (!json_response->IsArray()) {
    return false;
  }
  switch (json_response->Size()) {
    case 1: {
      std::unique_ptr<rapidjson::Document> value =
          ExtractElement(json_response.get(), &((*json_response)[0]));
      result->Success(value->IsNull() ? nullptr : value.get());
      return true;
    }
    case 3: {
      std::string code = (*json_response)[0].GetString();
      std::string message = (*json_response)[1].GetString();
      std::unique_ptr<rapidjson::Document> details =
          ExtractElement(json_response.get(), &((*json_response)[2]));
      result->Error(code, message, details->IsNull() ? nullptr : details.get());
      return true;
    }
    default:
      return false;
  }
}

}  // namespace flutter
