#pragma once

#include <cstdint>
#include <stdexcept>
#include <string>
#include <vector>

#include "toml.hpp"

#include "Formula.h"
#include "RecipesConfig.h"  // for RecipeIngredient

// Shared TOML-parsing helpers used by two or more ConfigLoader per-domain
// loaders. Helpers used by exactly one domain stay local to that domain's
// .cpp file instead.
//
// Namespaced because the names are generic: VisualsLoader.cpp and
// BalancingConfig.cpp each have their own same-named helpers in anonymous
// namespaces, and unqualified globals here would form an overload set with
// them the moment either file includes this header.
namespace utility
{

// --- Error helpers ----------------------------------------------------------

std::runtime_error makeError(const std::string& file,
                             const std::string& path,
                             const std::string& why);

// --- Typed accessors (throw on missing or wrong type) -----------------------

int64_t requireInt(const toml::node_view<toml::node>& node,
                   const std::string& file,
                   const std::string& path);

double requireDouble(const toml::node_view<toml::node>& node,
                     const std::string& file,
                     const std::string& path);

std::string requireString(const toml::node_view<toml::node>& node,
                          const std::string& file,
                          const std::string& path);

bool requireBool(const toml::node_view<toml::node>& node,
                 const std::string& file,
                 const std::string& path);

const toml::array& requireArray(const toml::node_view<toml::node>& node,
                                const std::string& file,
                                const std::string& path);

const toml::table& requireTable(const toml::node_view<toml::node>& node,
                                const std::string& file,
                                const std::string& path);

Formula requireFormula(const toml::node_view<toml::node>& node,
                       const std::string& file,
                       const std::string& path);

std::vector<std::string> requireStringArray(const toml::node_view<toml::node>& node,
                                            const std::string& file,
                                            const std::string& path);

std::vector<RecipeIngredient> parseIngredients(const toml::array& arr,
                                               const std::string& file,
                                               const std::string& path);

toml::table parseFile(const std::string& path, const std::string& file);

}  // namespace utility
