#include "config_parser.hpp"

#include <fmt/compile.h>
#include <fmt/format.h>

#include <functional>
#include <iterator>
#include <stdexcept>
#include <stdplus/exception.hpp>
#include <stdplus/fd/atomic.hpp>
#include <stdplus/fd/create.hpp>
#include <stdplus/fd/fmt.hpp>
#include <stdplus/fd/line.hpp>
#include <string>
#include <utility>

namespace phosphor
{
namespace network
{
namespace config
{

using std::literals::string_view_literals::operator""sv;

bool icaseeq(std::string_view in, std::string_view expected) noexcept
{
    return std::equal(in.begin(), in.end(), expected.begin(), expected.end(),
                      [](auto a, auto b) { return tolower(a) == b; });
}

std::optional<bool> parseBool(std::string_view in) noexcept
{
    if (in == "1"sv || icaseeq(in, "yes"sv) || icaseeq(in, "y"sv) ||
        icaseeq(in, "true"sv) || icaseeq(in, "t"sv) || icaseeq(in, "on"sv))
    {
        return true;
    }
    if (in == "0"sv || icaseeq(in, "no"sv) || icaseeq(in, "n"sv) ||
        icaseeq(in, "false"sv) || icaseeq(in, "f"sv) || icaseeq(in, "off"sv))
    {
        return false;
    }
    return std::nullopt;
}

fs::path pathForIntfConf(const fs::path& dir, std::string_view intf)
{
    return dir / fmt::format(FMT_COMPILE("00-bmc-{}.network"), intf);
}

fs::path pathForIntfDev(const fs::path& dir, std::string_view intf)
{
    return dir / fmt::format(FMT_COMPILE("{}.netdev"), intf);
}

const std::string*
    SectionMap::getLastValueString(std::string_view section,
                                   std::string_view key) const noexcept
{
    auto sit = find(section);
    if (sit == end())
    {
        return nullptr;
    }
    for (auto it = sit->second.rbegin(); it != sit->second.rend(); ++it)
    {
        auto kit = it->find(key);
        if (kit == it->end() || kit->second.empty())
        {
            continue;
        }
        return &kit->second.back().get();
    }
    return nullptr;
}

std::vector<std::string> SectionMap::getValueStrings(std::string_view section,
                                                     std::string_view key) const
{
    return getValues(section, key,
                     [](const Value& v) { return std::string(v); });
}

void KeyCheck::operator()(std::string_view s)
{
    for (auto c : s)
    {
        if (c == '\n' || c == '=')
        {
            throw std::invalid_argument(
                fmt::format(FMT_COMPILE("Invalid Config Key: {}"), s));
        }
    }
}

void SectionCheck::operator()(std::string_view s)
{
    for (auto c : s)
    {
        if (c == '\n' || c == ']')
        {
            throw std::invalid_argument(
                fmt::format(FMT_COMPILE("Invalid Config Section: {}"), s));
        }
    }
}

void ValueCheck::operator()(std::string_view s)
{
    for (auto c : s)
    {
        if (c == '\n')
        {
            throw std::invalid_argument(
                fmt::format(FMT_COMPILE("Invalid Config Value: {}"), s));
        }
    }
}

Parser::Parser(const fs::path& filename)
{
    setFile(filename);
}

constexpr bool isspace(char c) noexcept
{
    return c == ' ' || c == '\t';
}

constexpr bool iscomment(char c) noexcept
{
    return c == '#' || c == ';';
}

static void removePadding(std::string_view& str) noexcept
{
    size_t idx = str.size();
    for (; idx > 0 && isspace(str[idx - 1]); idx--)
        ;
    str.remove_suffix(str.size() - idx);

    idx = 0;
    for (; idx < str.size() && isspace(str[idx]); idx++)
        ;
    str.remove_prefix(idx);
}

struct Parse
{
    std::reference_wrapper<const fs::path> filename;
    SectionMap map;
    KeyValuesMap* section;
    std::vector<std::string> warnings;
    size_t lineno;

    inline Parse(const fs::path& filename) :
        filename(filename), section(nullptr), lineno(0)
    {
    }

    void pumpSection(std::string_view line)
    {
        auto cpos = line.find(']');
        if (cpos == line.npos)
        {
            warnings.emplace_back(fmt::format("{}:{}: Section missing ]",
                                              filename.get().native(), lineno));
        }
        else
        {
            for (auto c : line.substr(cpos + 1))
            {
                if (!isspace(c))
                {
                    warnings.emplace_back(
                        fmt::format("{}:{}: Characters outside section name",
                                    filename.get().native(), lineno));
                    break;
                }
            }
        }
        auto s = line.substr(0, cpos);
        auto it = map.find(s);
        if (it == map.end())
        {
            std::tie(it, std::ignore) = map.emplace(
                Section(Section::unchecked(), s), KeyValuesMapList{});
        }
        section = &it->second.emplace_back();
    }

    void pumpKV(std::string_view line)
    {
        auto epos = line.find('=');
        std::vector<std::string> new_warnings;
        if (epos == line.npos)
        {
            new_warnings.emplace_back(fmt::format(
                "{}:{}: KV missing `=`", filename.get().native(), lineno));
        }
        auto k = line.substr(0, epos);
        removePadding(k);
        if (section == nullptr)
        {
            new_warnings.emplace_back(
                fmt::format("{}:{}: Key `{}` missing section",
                            filename.get().native(), lineno, k));
        }
        if (!new_warnings.empty())
        {
            warnings.insert(warnings.end(),
                            std::make_move_iterator(new_warnings.begin()),
                            std::make_move_iterator(new_warnings.end()));
            return;
        }
        auto v = line.substr(epos + 1);
        removePadding(v);

        auto it = section->find(k);
        if (it == section->end())
        {
            std::tie(it, std::ignore) =
                section->emplace(Key(Key::unchecked(), k), ValueList{});
        }
        it->second.emplace_back(Value::unchecked(), v);
    }

    void pump(std::string_view line)
    {
        lineno++;
        for (size_t i = 0; i < line.size(); ++i)
        {
            auto c = line[i];
            if (iscomment(c))
            {
                return;
            }
            else if (c == '[')
            {
                return pumpSection(line.substr(i + 1));
            }
            else if (!isspace(c))
            {
                return pumpKV(line.substr(i));
            }
        }
    }
};

void Parser::setFile(const fs::path& filename)
{
    Parse parse(filename);

    bool fileExists = true;
    try
    {
        auto fd = stdplus::fd::open(filename.c_str(),
                                    stdplus::fd::OpenAccess::ReadOnly);
        stdplus::fd::LineReader reader(fd);
        while (true)
        {
            parse.pump(*reader.readLine());
        }
    }
    catch (const stdplus::exception::Eof&)
    {
    }
    catch (const std::system_error& e)
    {
        fileExists = false;
        // TODO: Pass exceptions once callers can handle them
        parse.warnings.emplace_back(
            fmt::format("{}: Open error: {}", filename.native(), e.what()));
    }

    this->map = std::move(parse.map);
    this->fileExists = fileExists;
    this->filename = filename;
    this->warnings = std::move(parse.warnings);
}

static void writeFileInt(const SectionMap& map, const fs::path& filename)
{
    stdplus::fd::AtomicWriter writer(filename, 0644);
    stdplus::fd::FormatBuffer out(writer);
    for (const auto& [section, maps] : map)
    {
        for (const auto& map : maps)
        {
            out.append(FMT_COMPILE("[{}]\n"), section.get());
            for (const auto& [key, vals] : map)
            {
                for (const auto& val : vals)
                {
                    out.append(FMT_COMPILE("{}={}\n"), key.get(), val.get());
                }
            }
        }
    }
    out.flush();
    writer.commit();
}

void Parser::writeFile() const
{
    writeFileInt(map, filename);
}

void Parser::writeFile(const fs::path& filename)
{
    writeFileInt(map, filename);
    this->filename = filename;
}

} // namespace config
} // namespace network
} // namespace phosphor
