/*
// Copyright (c) 2019 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/

#include "callback_manager.hpp"

#include <boost/asio/io_context.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/container/flat_map.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>

#include <variant>

constexpr const char* fatalLedPath =
    "/xyz/openbmc_project/led/groups/status_critical";
constexpr const char* criticalLedPath =
    "/xyz/openbmc_project/led/groups/status_non_critical";
constexpr const char* warningLedPath =
    "/xyz/openbmc_project/led/groups/status_degraded";
constexpr const char* okLedPath = "/xyz/openbmc_project/led/groups/status_ok";

constexpr const char* ledIface = "xyz.openbmc_project.Led.Group";
constexpr const char* ledAssertProp = "Asserted";
constexpr const char* ledManagerBusname =
    "xyz.openbmc_project.LED.GroupManager";

std::unique_ptr<AssociationManager> associationManager;

enum class StatusSetting
{
    none,
    ok,
    warn,
    critical,
    fatal
};

constexpr const bool debug = false;

// final led state tracking
StatusSetting currentPriority = StatusSetting::none;

// maps of <object-path, <property, asserted>>
boost::container::flat_map<std::string,
                           boost::container::flat_map<std::string, bool>>
    fatalAssertMap;
boost::container::flat_map<std::string,
                           boost::container::flat_map<std::string, bool>>
    criticalAssertMap;
boost::container::flat_map<std::string,
                           boost::container::flat_map<std::string, bool>>
    warningAssertMap;

std::vector<std::string> assertedInMap(
    const boost::container::flat_map<
        std::string, boost::container::flat_map<std::string, bool>>& map)
{
    std::vector<std::string> ret;
    // if any of the properties are true, return true
    for (const auto& pair : map)
    {
        for (const auto& item : pair.second)
        {
            if (item.second)
            {
                ret.push_back(pair.first);
            }
        }
    }
    return ret;
}

void updateLedStatus(std::shared_ptr<sdbusplus::asio::connection>& conn,
                     bool forceRefresh = false)
{
    std::vector<std::string> fatalVector = assertedInMap(fatalAssertMap);
    bool fatal = fatalVector.size();

    std::vector<std::string> criticalVector = assertedInMap(criticalAssertMap);
    bool critical = criticalVector.size();

    std::vector<std::string> warningVector = assertedInMap(warningAssertMap);
    bool warn = warningVector.size();

    associationManager->setLocalAssociations(fatalVector, criticalVector,
                                             warningVector);

    StatusSetting last = currentPriority;
    std::vector<std::pair<std::string, std::variant<bool>>> ledsToSet;
    if (forceRefresh)
    {
        ledsToSet.push_back(std::make_pair(fatalLedPath, false));
        ledsToSet.push_back(std::make_pair(criticalLedPath, false));
        ledsToSet.push_back(std::make_pair(warningLedPath, false));
        ledsToSet.push_back(std::make_pair(okLedPath, false));
        for (const auto& ledPair : ledsToSet)
        {
            conn->async_method_call(
                [ledPair](const boost::system::error_code ec) {
                    std::ios_base::fmtflags originalFlags = std::cerr.flags();
                    if (ec)
                    {
                        std::cerr << "Cannot set " << ledPair.first << " to "
                                  << std::boolalpha
                                  << std::get<bool>(ledPair.second) << "\n";
                        std::cerr.flags(originalFlags);
                    }
                    if constexpr (debug)
                    {
                        std::cerr << "Set " << ledPair.first << " to "
                                  << std::boolalpha
                                  << std::get<bool>(ledPair.second) << "\n";
                        std::cerr.flags(originalFlags);
                    }
                },
                ledManagerBusname, ledPair.first,
                "org.freedesktop.DBus.Properties", "Set", ledIface,
                ledAssertProp, ledPair.second);
        }
    }
    if (fatal)
    {
        currentPriority = StatusSetting::fatal;
    }
    else if (critical)
    {
        currentPriority = StatusSetting::critical;
    }
    else if (warn)
    {
        currentPriority = StatusSetting::warn;
    }
    else
    {
        currentPriority = StatusSetting::ok;
    }

    if (last != currentPriority || forceRefresh)
    {
        switch (currentPriority)
        {
            case (StatusSetting::fatal):
            {
                ledsToSet.push_back(std::make_pair(fatalLedPath, true));
                ledsToSet.push_back(std::make_pair(criticalLedPath, false));
                ledsToSet.push_back(std::make_pair(warningLedPath, false));
                ledsToSet.push_back(std::make_pair(okLedPath, false));
                break;
            }
            case (StatusSetting::critical):
            {
                ledsToSet.push_back(std::make_pair(fatalLedPath, false));
                ledsToSet.push_back(std::make_pair(criticalLedPath, true));
                ledsToSet.push_back(std::make_pair(warningLedPath, false));
                ledsToSet.push_back(std::make_pair(okLedPath, false));
                break;
            }
            case (StatusSetting::warn):
            {
                ledsToSet.push_back(std::make_pair(fatalLedPath, false));
                ledsToSet.push_back(std::make_pair(criticalLedPath, false));
                ledsToSet.push_back(std::make_pair(warningLedPath, true));
                ledsToSet.push_back(std::make_pair(okLedPath, false));
                break;
            }
            case (StatusSetting::ok):
            {
                ledsToSet.push_back(std::make_pair(fatalLedPath, false));
                ledsToSet.push_back(std::make_pair(criticalLedPath, false));
                ledsToSet.push_back(std::make_pair(warningLedPath, false));
                ledsToSet.push_back(std::make_pair(okLedPath, true));
                break;
            }
        }
    }

    for (const auto& ledPair : ledsToSet)
    {
        conn->async_method_call(
            [ledPair](const boost::system::error_code ec) {
                if (ec)
                {
                    std::cerr << "Cannot set " << ledPair.first << " to "
                              << std::boolalpha
                              << std::get<bool>(ledPair.second) << "\n";
                }
                if constexpr (debug)
                {
                    std::cerr
                        << "Set " << ledPair.first << " to " << std::boolalpha
                        << std::get<bool>(ledPair.second) << "\n";
                }
            },
            ledManagerBusname, ledPair.first, "org.freedesktop.DBus.Properties",
            "Set", ledIface, ledAssertProp, ledPair.second);
    }
}

void createThresholdMatch(std::shared_ptr<sdbusplus::asio::connection>& conn)
{
    static sdbusplus::bus::match_t match(
        static_cast<sdbusplus::bus_t&>(*conn),
        "type='signal',member='ThresholdAsserted'",
        [&conn](sdbusplus::message_t& message) {
            std::string sensorName;
            std::string thresholdInterface;
            std::string event;
            bool assert;
            double assertValue;

            try
            {
                message.read(sensorName, thresholdInterface, event, assert,
                             assertValue);
            }
            catch (sdbusplus::exception_t&)
            {
                return;
            }
            if constexpr (debug)
            {
                std::cerr << "Threshold callback: SensorName = " << sensorName
                          << ", Event = " << event << ", Asserted = " << assert
                          << "\n";
            }

            if (event == "CriticalAlarmLow")
            {
                criticalAssertMap[message.get_path()]["low"] = assert;
            }
            else if (event == "CriticalAlarmHigh")
            {
                criticalAssertMap[message.get_path()]["high"] = assert;
            }
            else if (event == "WarningAlarmLow")
            {
                warningAssertMap[message.get_path()]["low"] = assert;
            }
            else if (event == "WarningAlarmHigh")
            {
                warningAssertMap[message.get_path()]["high"] = assert;
            }

            associationManager->setSensorAssociations(
                assertedInMap(criticalAssertMap),
                assertedInMap(warningAssertMap));

            updateLedStatus(conn);
        });
}

void createAssociationMatch(std::shared_ptr<sdbusplus::asio::connection>& conn)
{
    static sdbusplus::bus::match_t match(
        static_cast<sdbusplus::bus_t&>(*conn),
        "type='signal',interface='org.freedesktop.DBus.Properties',"
        "arg0namespace='" +
            std::string(associationIface) + "'",
        [&conn](sdbusplus::message_t& message) {
            if (message.get_path() == rootPath)
            {
                return; // it's us
            }
            std::string objectName;
            boost::container::flat_map<std::string,
                                       std::variant<std::vector<Association>>>
                values;
            try
            {
                message.read(objectName, values);
            }
            catch (sdbusplus::exception_t&)
            {
                return;
            }

            if constexpr (debug)
            {
                std::cerr << "Association callback " << message.get_path()
                          << "\n";
            }

            auto findAssociations = values.find("Associations");
            if (findAssociations == values.end())
            {
                return;
            }
            const std::vector<Association>* associations =
                std::get_if<std::vector<Association>>(
                    &findAssociations->second);

            if (associations == nullptr)
            {
                std::cerr << "Illegal Association on " << message.get_path()
                          << "\n";
                return;
            }

            bool localWarning = false;
            bool localCritical = false;
            bool globalWarning = false;
            bool globalCritical = false;

            for (const auto& [forward, reverse, path] : *associations)
            {
                if (path == rootPath)
                {
                    globalWarning = globalWarning ? true : reverse == "warning";
                    globalCritical =
                        globalCritical ? true : reverse == "critical";

                    if constexpr (1)
                    {
                        std::cerr << "got global ";
                    }
                }
                else
                {
                    localWarning = localWarning ? true : reverse == "warning";
                    localCritical =
                        localCritical ? true : reverse == "critical";
                }
                if (globalCritical && localCritical)
                {
                    break;
                }
            }

            bool fatal = globalCritical && localCritical;
            bool critical = globalWarning && localCritical;
            bool warning = globalWarning && !critical;

            fatalAssertMap[message.get_path()]["association"] = fatal;
            criticalAssertMap[message.get_path()]["association"] = critical;
            warningAssertMap[message.get_path()]["association"] = warning;

            updateLedStatus(conn);
        });
}

int main(int argc, char** argv)
{
    boost::asio::io_context io;
    auto conn = std::make_shared<sdbusplus::asio::connection>(io);
    conn->request_name("xyz.openbmc_project.CallbackManager");
    sdbusplus::asio::object_server objServer(conn);
    std::shared_ptr<sdbusplus::asio::dbus_interface> rootIface =
        objServer.add_interface(rootPath,
                                "xyz.openbmc_project.CallbackManager");
    rootIface->register_method("RetriggerLEDUpdate", [&conn]() {
        updateLedStatus(conn, true);
    });
    rootIface->initialize();

    std::shared_ptr<sdbusplus::asio::dbus_interface> inventoryIface =
        objServer.add_interface(rootPath, globalInventoryIface);
    inventoryIface->initialize();

    associationManager = std::make_unique<AssociationManager>(objServer, conn);

    createThresholdMatch(conn);
    createAssociationMatch(conn);
    updateLedStatus(conn);

    io.run();

    return 0;
}
