#include "util.hpp"

#include <cmath>
#include <cstdint>
#include <iostream>
#include <map>
#include <regex>
#include <set>
#include <string>
#include <unordered_map>
#include <utility>
#include <variant>
#include <vector>

using Property = std::string;
using Value = std::variant<int64_t, double, std::string, bool>;
using PropertyMap = std::map<Property, Value>;

namespace pid_control
{

int64_t setZoneIndex(const std::string& name,
                     std::map<std::string, int64_t>& zones, int64_t index)
{
    auto it = zones.find(name);
    if (it != zones.end())
    {
        // Name already allocated, make no change, return existing
        return it->second;
    }

    // The zone name is known not to exist yet
    for (;;)
    {
        bool usedIndex = false;

        // See if desired index number is free
        for (const auto& zi : zones)
        {
            if (index == zi.second)
            {
                usedIndex = true;
                break;
            }
        }

        // Increment until a free index number is found
        if (usedIndex)
        {
            ++index;
            continue;
        }

        break;
    }

    // Allocate and return new zone index number for this name
    zones[name] = index;
    return index;
}

int64_t getZoneIndex(const std::string& name,
                     std::map<std::string, int64_t>& zones)
{
    auto it = zones.find(name);
    if (it != zones.end())
    {
        return it->second;
    }

    // Auto-assign next unused zone number, using 0-based numbering
    return setZoneIndex(name, zones, 0);
}

bool findSensors(const std::unordered_map<std::string, std::string>& sensors,
                 const std::string& search,
                 std::vector<std::pair<std::string, std::string>>& matches)
{
    std::smatch match;
    std::regex reg(search + '$');
    for (const auto& sensor : sensors)
    {
        if (std::regex_search(sensor.first, match, reg))
        {
            matches.push_back(sensor);
        }
    }
    return matches.size() > 0;
}

std::string getSensorPath(const std::string& type, const std::string& id)
{
    std::string layer = type;
    if (type == "fan")
    {
        layer = "fan_tach";
    }
    else if (type == "temp")
    {
        layer = "temperature";
    }
    else if (type == "margin")
    {
        layer = "temperature";
    }
    else
    {
        layer = "unknown"; // TODO(venture): Need to handle.
    }

    return std::string("/xyz/openbmc_project/sensors/" + layer + "/" + id);
}

std::string getMatch(const std::string& type, const std::string& id)
{
    return std::string("type='signal',"
                       "interface='org.freedesktop.DBus.Properties',"
                       "member='PropertiesChanged',"
                       "path='" +
                       getSensorPath(type, id) + "'");
}

bool validType(const std::string& type)
{
    static std::set<std::string> valid = {"fan", "temp", "margin"};
    return (valid.find(type) != valid.end());
}

void scaleSensorReading(const double min, const double max, double& value)
{
    if (max <= 0 || max <= min)
    {
        return;
    }
    value -= min;
    value /= (max - min);
}

} // namespace pid_control
