// 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/json_method_codec.h"

#include "flutter/shell/platform/common/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]));
      if (value->IsNull()) {
        result->Success();
      } else {
        result->Success(*value);
      }
      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]));
      if (details->IsNull()) {
        result->Error(code, message);
      } else {
        result->Error(code, message, *details);
      }
      return true;
    }
    default:
      return false;
  }
}

}  // namespace flutter
