// Copyright 2019 Google LLC
//
// 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
//
//     https://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 "rapid_json_serializer.h"

#include "null_json_serializer.h"

#include <rapidjson/document.h>
#include <rapidjson/prettywriter.h>

namespace dap {
namespace json {

RapidDeserializer::RapidDeserializer(const std::string& str)
    : doc(new rapidjson::Document()) {
  doc->Parse(str.c_str());
}

RapidDeserializer::RapidDeserializer(rapidjson::Value* json) : val(json) {}

RapidDeserializer::~RapidDeserializer() {
  delete doc;
}

bool RapidDeserializer::deserialize(dap::boolean* v) const {
  if (!json()->IsBool()) {
    return false;
  }
  *v = json()->GetBool();
  return true;
}

bool RapidDeserializer::deserialize(dap::integer* v) const {
  if (!json()->IsInt()) {
    return false;
  }
  *v = json()->GetInt();
  return true;
}

bool RapidDeserializer::deserialize(dap::number* v) const {
  if (!json()->IsNumber()) {
    return false;
  }
  *v = json()->GetDouble();
  return true;
}

bool RapidDeserializer::deserialize(dap::string* v) const {
  if (!json()->IsString()) {
    return false;
  }
  *v = json()->GetString();
  return true;
}

bool RapidDeserializer::deserialize(dap::object* v) const {
  v->reserve(json()->MemberCount());
  for (auto el = json()->MemberBegin(); el != json()->MemberEnd(); el++) {
    dap::any val;
    RapidDeserializer d(&(el->value));
    if (!d.deserialize(&val)) {
      return false;
    }
    (*v)[el->name.GetString()] = val;
  }
  return true;
}

bool RapidDeserializer::deserialize(dap::any* v) const {
  if (json()->IsBool()) {
    *v = dap::boolean(json()->GetBool());
  } else if (json()->IsDouble()) {
    *v = dap::number(json()->GetDouble());
  } else if (json()->IsInt()) {
    *v = dap::integer(json()->GetInt());
  } else if (json()->IsString()) {
    *v = dap::string(json()->GetString());
  } else if (json()->IsNull()) {
    *v = null();
  } else {
    return false;
  }
  return true;
}

size_t RapidDeserializer::count() const {
  return json()->Size();
}

bool RapidDeserializer::array(
    const std::function<bool(dap::Deserializer*)>& cb) const {
  if (!json()->IsArray()) {
    return false;
  }
  for (uint32_t i = 0; i < json()->Size(); i++) {
    RapidDeserializer d(&(*json())[i]);
    if (!cb(&d)) {
      return false;
    }
  }
  return true;
}

bool RapidDeserializer::field(
    const std::string& name,
    const std::function<bool(dap::Deserializer*)>& cb) const {
  if (!json()->IsObject()) {
    return false;
  }
  auto it = json()->FindMember(name.c_str());
  if (it == json()->MemberEnd()) {
    return cb(&NullDeserializer::instance);
  }
  RapidDeserializer d(&(it->value));
  return cb(&d);
}

RapidSerializer::RapidSerializer()
    : doc(new rapidjson::Document(rapidjson::kObjectType)),
      allocator(doc->GetAllocator()) {}

RapidSerializer::RapidSerializer(rapidjson::Value* json,
                                 rapidjson::Document::AllocatorType& allocator)
    : val(json), allocator(allocator) {}

RapidSerializer::~RapidSerializer() {
  delete doc;
}

std::string RapidSerializer::dump() const {
  rapidjson::StringBuffer sb;
  rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(sb);
  json()->Accept(writer);
  return sb.GetString();
}

bool RapidSerializer::serialize(dap::boolean v) {
  json()->SetBool(v);
  return true;
}

bool RapidSerializer::serialize(dap::integer v) {
  json()->SetInt64(v);
  return true;
}

bool RapidSerializer::serialize(dap::number v) {
  json()->SetDouble(v);
  return true;
}

bool RapidSerializer::serialize(const dap::string& v) {
  json()->SetString(v.data(), static_cast<uint32_t>(v.length()), allocator);
  return true;
}

bool RapidSerializer::serialize(const dap::object& v) {
  if (!json()->IsObject()) {
    json()->SetObject();
  }
  for (auto& it : v) {
    if (!json()->HasMember(it.first.c_str())) {
      rapidjson::Value name_value{it.first.c_str(), allocator};
      json()->AddMember(name_value, rapidjson::Value(), allocator);
    }
    rapidjson::Value& member = (*json())[it.first.c_str()];
    RapidSerializer s(&member, allocator);
    if (!s.serialize(it.second)) {
      return false;
    }
  }
  return true;
}

bool RapidSerializer::serialize(const dap::any& v) {
  if (v.is<dap::boolean>()) {
    json()->SetBool((bool)v.get<dap::boolean>());
  } else if (v.is<dap::integer>()) {
    json()->SetInt((int)v.get<dap::integer>());
  } else if (v.is<dap::number>()) {
    json()->SetDouble((double)v.get<dap::number>());
  } else if (v.is<dap::string>()) {
    auto s = v.get<dap::string>();
    json()->SetString(s.data(), static_cast<uint32_t>(s.length()), allocator);
  } else if (v.is<dap::null>()) {
  } else {
    return false;
  }

  return true;
}

bool RapidSerializer::array(size_t count,
                            const std::function<bool(dap::Serializer*)>& cb) {
  if (!json()->IsArray()) {
    json()->SetArray();
  }

  while (count > json()->Size()) {
    json()->PushBack(rapidjson::Value(), allocator);
  }

  for (uint32_t i = 0; i < count; i++) {
    RapidSerializer s(&(*json())[i], allocator);
    if (!cb(&s)) {
      return false;
    }
  }
  return true;
}

bool RapidSerializer::object(
    const std::function<bool(dap::FieldSerializer*)>& cb) {
  struct FS : public FieldSerializer {
    rapidjson::Value* const json;
    rapidjson::Document::AllocatorType& allocator;

    FS(rapidjson::Value* json, rapidjson::Document::AllocatorType& allocator)
        : json(json), allocator(allocator) {}
    bool field(const std::string& name, const SerializeFunc& cb) override {
      if (!json->HasMember(name.c_str())) {
        rapidjson::Value name_value{name.c_str(), allocator};
        json->AddMember(name_value, rapidjson::Value(), allocator);
      }
      rapidjson::Value& member = (*json)[name.c_str()];
      RapidSerializer s(&member, allocator);
      auto res = cb(&s);
      if (s.removed) {
        json->RemoveMember(name.c_str());
      }
      return res;
    }
  };

  if (!json()->IsObject()) {
    json()->SetObject();
  }
  FS fs{json(), allocator};
  return cb(&fs);
}

void RapidSerializer::remove() {
  removed = true;
}

}  // namespace json
}  // namespace dap
