#pragma once
#include "stringcompare.h"
#include "stringtrim.h"
#include <algorithm>
#include <functional>
#include <vector>
#include <string>

namespace myapp::utils {

constexpr auto params_separator = ';';
constexpr auto value_separator = '=';

inline std::vector<std::string> split_parameters(std::string const& str, char separator = params_separator)
{
    std::vector<std::string> result;

    std::string::size_type first1 = 0;
    do
    {
        auto last1 = str.find_first_of(separator, first1);
        std::string sub;

        if (last1 != std::string::npos)
        {
            sub = str.substr(first1, last1 - first1);
            first1 = last1 + 1;
        }
        else
        {
            sub = str.substr(first1);
            first1 = std::string::npos;
        }

        if (!sub.empty())
        {
            utils::trim(sub);
            result.emplace_back(std::move(sub));
        }
    } while (first1 != std::string::npos);

    return result;
}

inline std::string extract_parameter(
    std::vector<std::string>& params,
    std::string const& prefix,
    bool optional = true)
{
    using namespace std::string_literals;

    auto pos = std::find_if(begin(params) + 1, end(params), [&prefix](std::string const& param)
    {
        return utils::starts_with(param, prefix);
    });

    if (pos != end(params))
    {
        auto result = std::move(*pos);
        result.erase(0, prefix.size());
        utils::trim(result);
        return result;
    }

    if (!optional)
        throw std::runtime_error("Required parameter '"s + prefix + "' not found in connection string"s);

    return std::string{};
}

inline void extract_parameter_and_invoke_if_present(
    std::vector<std::string>& params,
    std::string const& prefix,
    std::function<void(std::string)> f)
{
    using namespace std::string_literals;

    auto str = extract_parameter(params, "period"s + value_separator);
    if (!str.empty())
    {
        f(std::move(str));
    }
}


} /* namespace myapp::utils */
