#include "ini_parser.h"

#include <string>
#include <iostream>
#include <cctype>

namespace {

void Lstrip(std::string& line)
{
    size_t pos = 0;
    for (; pos < line.size() && std::isspace(line[pos]); ++pos);
    line = line.substr(pos);
}

void Rstrip(std::string& line)
{
    int pos = static_cast<int>(line.size()) - 1;
    for (; pos >= 0 && std::isspace(line[pos]); --pos);
    line = line.substr(0, pos + 1);
}

void Strip(std::string& s)
{
    Rstrip(s);
    Lstrip(s);
}

} // namespace

namespace maps::mrc::drive::Cfg {

Section& IniSettings::addSection(const std::string& name)
{
    return sections_[name];
}

const Section& IniSettings::getSection(const std::string& name) const
{
    return sections_.at(name);
}

IniSettings load(std::istream& input)
{
    IniSettings result;

    Section* currentSection = nullptr;
    for (std::string line; getline(input, line);) {
        if (!line.empty() && line[0] != '#') {
            if (line[0] == '[') {
                currentSection = &result.addSection(line.substr(1, line.size() - 2));
            } else {
                size_t pos = line.find('=');
                if (pos != std::string::npos) {
                    std::string nameStr = line.substr(0, pos);
                    std::string valueStr = line.substr(pos + 1);
                    Strip(nameStr);
                    Strip(valueStr);
                    currentSection->insert({move(nameStr), move(valueStr)});
                }
            }
        }
    }

    return result;
}

} // namespace maps::mrc::drive::Cfg