#pragma once

#include "foundation/result.h"

#include <cstddef>
#include <cstdint>
#include <string>
#include <string_view>
#include <variant>
#include <vector>

namespace pp::assets {

constexpr std::size_t max_settings_entries = 4096;
constexpr std::size_t max_settings_key_length = 128;
constexpr std::size_t max_settings_string_length = 4096;

using SettingsValue = std::variant<bool, std::int64_t, double, std::string>;

struct SettingsEntry {
    std::string key;
    SettingsValue value;
};

class SettingsDocument {
public:
    [[nodiscard]] std::size_t size() const noexcept;
    [[nodiscard]] bool empty() const noexcept;
    [[nodiscard]] bool has(std::string_view key) const noexcept;
    [[nodiscard]] const std::vector<SettingsEntry>& entries() const noexcept;

    [[nodiscard]] pp::foundation::Status set(std::string_view key, SettingsValue value);
    [[nodiscard]] pp::foundation::Result<SettingsValue> get(std::string_view key) const;
    [[nodiscard]] pp::foundation::Status unset(std::string_view key) noexcept;
    void clear() noexcept;

private:
    [[nodiscard]] std::vector<SettingsEntry>::iterator find_entry(std::string_view key) noexcept;
    [[nodiscard]] std::vector<SettingsEntry>::const_iterator find_entry(std::string_view key) const noexcept;

    std::vector<SettingsEntry> entries_;
};

[[nodiscard]] pp::foundation::Status validate_settings_key(std::string_view key) noexcept;
[[nodiscard]] pp::foundation::Status validate_settings_value(const SettingsValue& value) noexcept;
[[nodiscard]] const char* settings_value_type_name(const SettingsValue& value) noexcept;

}
