#pragma once

#include "serializer.h"

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

class JsonReader : public Reader
{

    std::vector<char const*> path_;

public:
    rapidjson::GenericValue<rapidjson::UTF8<>>* m_;
    JsonReader(rapidjson::GenericValue<rapidjson::UTF8<>>* m) : m_(m)
    {
    }
    SerializeFormat Format() const override
    {
        return SerializeFormat::Json;
    }

    bool IsBool() override
    {
        return m_->IsBool();
    }
    bool IsNull() override
    {
        return m_->IsNull();
    }
    bool IsArray() override
    {
        return m_->IsArray();
    }
    bool IsInt() override
    {
        return m_->IsInt();
    }
    bool IsInt64() override
    {
        return m_->IsInt64();
    }
    bool IsUint64() override
    {
        return m_->IsUint64();
    }
    bool IsDouble() override
    {
        return m_->IsDouble();
    }
    bool IsNumber() override
    {
        return m_->IsNumber();
    }
    bool IsString() override
    {
        return m_->IsString();
    }

    void GetNull() override
    {
    }
    bool GetBool() override
    {
        return m_->GetBool();
    }
    int GetInt() override
    {
        return m_->GetInt();
    }
    uint32_t GetUint32() override
    {
        return static_cast<uint32_t>(m_->GetUint64());
    }
    int64_t GetInt64() override
    {
        return m_->GetInt64();
    }
    uint64_t GetUint64() override
    {
        return m_->GetUint64();
    }
    double GetDouble() override
    {
        return m_->GetDouble();
    }
    std::string GetString() override
    {
        return m_->GetString();
    }

    bool HasMember(char const* x) override
    {
        if (m_->IsObject())
        {
            return m_->HasMember(x);
        }
        else
        {
            return false;
        }
    }
    std::unique_ptr<Reader> operator[](char const* x) override
    {
        auto& sub = (*m_)[x];
        return std::unique_ptr<JsonReader>(new JsonReader(&sub));
    }

    std::string ToString() const override;

    void IterMap(std::function<void(char const*, Reader&)> fn) override;

    void IterArray(std::function<void(Reader&)> fn) override;

    void DoMember(char const* name, std::function<void(Reader&)> fn) override;

    std::string GetPath() const;
};

class JsonWriter : public Writer
{

public:
    rapidjson::Writer<rapidjson::StringBuffer>* m_;

    JsonWriter(rapidjson::Writer<rapidjson::StringBuffer>* m) : m_(m)
    {
    }
    SerializeFormat Format() const override
    {
        return SerializeFormat::Json;
    }

    void Null() override
    {
        m_->Null();
    }
    void Bool(bool x) override
    {
        m_->Bool(x);
    }
    void Int(int x) override
    {
        m_->Int(x);
    }
    void Uint32(uint32_t x) override
    {
        m_->Uint64(x);
    }
    void Int64(int64_t x) override
    {
        m_->Int64(x);
    }
    void Uint64(uint64_t x) override
    {
        m_->Uint64(x);
    }
    void Double(double x) override
    {
        m_->Double(x);
    }
    void String(char const* x) override
    {
        m_->String(x);
    }
    void String(char const* x, size_t len) override
    {
        m_->String(x, len);
    }
    void StartArray(size_t) override
    {
        m_->StartArray();
    }
    void EndArray() override
    {
        m_->EndArray();
    }
    void StartObject() override
    {
        m_->StartObject();
    }
    void EndObject() override
    {
        m_->EndObject();
    }
    void Key(char const* name) override
    {
        m_->Key(name);
    }
};
