#ifndef TILE_BASE_CONFIG_JSON_CONFIGURATION_H
#define TILE_BASE_CONFIG_JSON_CONFIGURATION_H

#pragma once

#include "tile/base/config/configuration.h"
#include "json/json.h"

namespace tile {
class JSONConfiguration : public Configuration {
public:
    using Ptr = RefPtr<JSONConfiguration>;
    JSONConfiguration();
    ~JSONConfiguration() override;
    bool load(const std::string &path);
    bool load(std::istream &istr);

    void SetInt(const Slice &key, int value) override;
    void SetBool(const Slice &key, bool value) override;
    void SetDouble(const Slice &key, double value) override;
    void SetString(const Slice &key, const std::string &value) override;
    void RemoveRaw(const Slice &key) override;

    std::string Dump() const;

protected:
    bool GetRaw(const Slice &key, std::string *value) const override;
    bool SetRaw(const Slice &key, const Slice &value) override;
    Keys Enumerate(const Slice &range) const override;

private:
    bool FindStart(const Slice &key, Slice *last_prt, Json::Value **parent_obj);
    template<typename T>
    bool SetValue(const Slice &key, T value);
    Json::Value object_;
};

template<typename T>
bool
JSONConfiguration::SetValue(const Slice &key, T value)
{
    Slice last_part;
    Json::Value *root;
    if (!FindStart(key, &last_part, &root)) { return false; }
    (*root)[last_part] = Json::Value(value);
    return true;
}
}// namespace tile

#endif// TILE_BASE_CONFIG_JSON_CONFIGURATION_H
