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

#include "null_json_serializer.h"

// Disable JSON exceptions. We should be guarding against any exceptions being
// fired in this file.
#define JSON_NOEXCEPTION 1
#include <nlohmann/json.hpp>

namespace dap {
namespace json {

NlohmannDeserializer::NlohmannDeserializer(const std::string& str)
    : json(new nlohmann::json(nlohmann::json::parse(str, nullptr, false))),
      ownsJson(true) {}

NlohmannDeserializer::NlohmannDeserializer(const nlohmann::json* json)
    : json(json), ownsJson(false) {}

NlohmannDeserializer::~NlohmannDeserializer() {
  if (ownsJson) {
    delete json;
  }
}

bool NlohmannDeserializer::deserialize(dap::boolean* v) const {
  if (!json->is_boolean()) {
    return false;
  }
  *v = json->get<bool>();
  return true;
}

bool NlohmannDeserializer::deserialize(dap::integer* v) const {
  if (!json->is_number_integer()) {
    return false;
  }
  *v = json->get<int>();
  return true;
}

bool NlohmannDeserializer::deserialize(dap::number* v) const {
  if (!json->is_number()) {
    return false;
  }
  *v = json->get<double>();
  return true;
}

bool NlohmannDeserializer::deserialize(dap::string* v) const {
  if (!json->is_string()) {
    return false;
  }
  *v = json->get<std::string>();
  return true;
}

bool NlohmannDeserializer::deserialize(dap::object* v) const {
  v->reserve(json->size());
  for (auto& el : json->items()) {
    NlohmannDeserializer d(&el.value());
    dap::any val;
    if (!d.deserialize(&val)) {
      return false;
    }
    (*v)[el.key()] = val;
  }
  return true;
}

bool NlohmannDeserializer::deserialize(dap::any* v) const {
  if (json->is_boolean()) {
    *v = dap::boolean(json->get<bool>());
  } else if (json->is_number_float()) {
    *v = dap::number(json->get<double>());
  } else if (json->is_number_integer()) {
    *v = dap::integer(json->get<int>());
  } else if (json->is_string()) {
    *v = json->get<std::string>();
  } else if (json->is_null()) {
    *v = null();
  } else {
    return false;
  }
  return true;
}

size_t NlohmannDeserializer::count() const {
  return json->size();
}

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

bool NlohmannDeserializer::field(
    const std::string& name,
    const std::function<bool(dap::Deserializer*)>& cb) const {
  if (!json->is_structured()) {
    return false;
  }
  auto it = json->find(name);
  if (it == json->end()) {
    return cb(&NullDeserializer::instance);
  }
  auto obj = *it;
  NlohmannDeserializer d(&obj);
  return cb(&d);
}

NlohmannSerializer::NlohmannSerializer()
    : json(new nlohmann::json()), ownsJson(true) {}

NlohmannSerializer::NlohmannSerializer(nlohmann::json* json)
    : json(json), ownsJson(false) {}

NlohmannSerializer::~NlohmannSerializer() {
  if (ownsJson) {
    delete json;
  }
}

std::string NlohmannSerializer::dump() const {
  return json->dump();
}

bool NlohmannSerializer::serialize(dap::boolean v) {
  *json = (bool)v;
  return true;
}

bool NlohmannSerializer::serialize(dap::integer v) {
  *json = (int)v;
  return true;
}

bool NlohmannSerializer::serialize(dap::number v) {
  *json = (double)v;
  return true;
}

bool NlohmannSerializer::serialize(const dap::string& v) {
  *json = v;
  return true;
}

bool NlohmannSerializer::serialize(const dap::object& v) {
  for (auto& it : v) {
    NlohmannSerializer s(&(*json)[it.first]);
    if (!s.serialize(it.second)) {
      return false;
    }
  }
  return true;
}

bool NlohmannSerializer::serialize(const dap::any& v) {
  if (v.is<dap::boolean>()) {
    *json = (bool)v.get<dap::boolean>();
  } else if (v.is<dap::integer>()) {
    *json = (int)v.get<dap::integer>();
  } else if (v.is<dap::number>()) {
    *json = (double)v.get<dap::number>();
  } else if (v.is<dap::string>()) {
    *json = v.get<dap::string>();
  } else if (v.is<dap::null>()) {
  } else {
    return false;
  }

  return true;
}

bool NlohmannSerializer::array(
    size_t count,
    const std::function<bool(dap::Serializer*)>& cb) {
  *json = std::vector<int>();
  for (size_t i = 0; i < count; i++) {
    NlohmannSerializer s(&(*json)[i]);
    if (!cb(&s)) {
      return false;
    }
  }
  return true;
}

bool NlohmannSerializer::object(
    const std::function<bool(dap::FieldSerializer*)>& cb) {
  struct FS : public FieldSerializer {
    nlohmann::json* const json;

    FS(nlohmann::json* json) : json(json) {}
    bool field(const std::string& name, const SerializeFunc& cb) override {
      NlohmannSerializer s(&(*json)[name]);
      auto res = cb(&s);
      if (s.removed) {
        json->erase(name);
      }
      return res;
    }
  };

  *json = nlohmann::json({}, false, nlohmann::json::value_t::object);
  FS fs{json};
  return cb(&fs);
}

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

}  // namespace json
}  // namespace dap
