#pragma once
#include "JsonNode.hpp"
#include <utility>
#include <vector>
#include "UniquePtr.hpp"
NAMESPACE_SOUP
{
struct JsonObject : public JsonNode
{
using Container = std::vector<std::pair<UniquePtr<JsonNode>, UniquePtr<JsonNode>>>;
Container children{};
explicit JsonObject() noexcept;
explicit JsonObject(const char*& c, int max_depth) noexcept;
void encodeAndAppendTo(std::string& str) const SOUP_EXCAL final;
void encodePrettyAndAppendTo(std::string& str, unsigned depth = 0) const SOUP_EXCAL;
bool binaryEncode(Writer& w) const final;
[[nodiscard]] JsonNode* find(std::string k) const noexcept;
[[nodiscard]] JsonNode* find(const JsonNode& k) const noexcept;
[[nodiscard]] UniquePtr<JsonNode>* findUp(std::string k) noexcept;
[[nodiscard]] UniquePtr<JsonNode>* findUp(const JsonNode& k) noexcept;
[[nodiscard]] Container::iterator findIt(std::string k) noexcept;
[[nodiscard]] Container::iterator findIt(const JsonNode& k) noexcept;
[[nodiscard]] bool contains(const JsonNode& k) const noexcept;
[[nodiscard]] bool contains(std::string k) const noexcept;
[[nodiscard]] JsonNode& at(const JsonNode& k) const;
[[nodiscard]] JsonNode& at(std::string k) const;
void erase(const JsonNode& k) noexcept;
void erase(std::string k) noexcept;
void erase(Container::const_iterator it) noexcept;
void clear() noexcept;
[[nodiscard]] auto begin() noexcept { return children.begin(); }
[[nodiscard]] auto end() noexcept { return children.end(); }
[[nodiscard]] auto begin() const noexcept { return children.begin(); }
[[nodiscard]] auto end() const noexcept { return children.end(); }
void add(UniquePtr<JsonNode>&& k, UniquePtr<JsonNode>&& v);
void add(std::string k, std::string v);
void add(std::string k, const char* v);
void add(std::string k, int8_t v);
void add(std::string k, int16_t v);
void add(std::string k, int32_t v);
void add(std::string k, uint32_t v);
void add(std::string k, int64_t v);
void add(std::string k, bool v);
void add(std::string k, double v);
template <typename T, SOUP_RESTRICT(std::is_base_of_v<JsonNode, T>)>
void add(std::string k, UniquePtr<T>&& v)
{
add(soup::make_unique<JsonString>(std::move(k)), std::move(v));
}
};
}