/**
 * Copyright © 2020 IBM 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 "event.hpp"

#include "action.hpp"
#include "config_base.hpp"
#include "group.hpp"
#include "manager.hpp"
#include "sdbusplus.hpp"
#include "trigger.hpp"

#include <nlohmann/json.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>

#include <algorithm>
#include <format>
#include <optional>

namespace phosphor::fan::control::json
{

using json = nlohmann::json;
using namespace phosphor::logging;

std::map<configKey, std::unique_ptr<Group>> Event::allGroups;

Event::Event(const json& jsonObj, Manager* mgr,
             std::map<configKey, std::unique_ptr<Zone>>& zones) :
    ConfigBase(jsonObj), _bus(util::SDBusPlus::getBus()), _manager(mgr),
    _zones(zones)
{
    // Event groups are optional
    if (jsonObj.contains("groups"))
    {
        setGroups(jsonObj, _profiles, _groups);
    }
    // Event actions are optional
    if (jsonObj.contains("actions"))
    {
        setActions(jsonObj);
    }
    setTriggers(jsonObj);
}

void Event::enable()
{
    for (const auto& [type, trigger] : _triggers)
    {
        // Don't call the powerOn or powerOff triggers
        if (type.find("power") == std::string::npos)
        {
            trigger(getName(), _manager, _groups, _actions);
        }
    }
}

void Event::powerOn()
{
    for (const auto& [type, trigger] : _triggers)
    {
        if (type == "poweron")
        {
            trigger(getName(), _manager, _groups, _actions);
        }
    }
}

void Event::powerOff()
{
    for (const auto& [type, trigger] : _triggers)
    {
        if (type == "poweroff")
        {
            trigger(getName(), _manager, _groups, _actions);
        }
    }
}

std::map<configKey, std::unique_ptr<Group>>&
    Event::getAllGroups(bool loadGroups)
{
    if (allGroups.empty() && loadGroups)
    {
        allGroups = Manager::getConfig<Group>(true);
    }

    return allGroups;
}

void Event::configGroup(Group& group, const json& jsonObj)
{
    if (!jsonObj.contains("interface") || !jsonObj.contains("property") ||
        !jsonObj["property"].contains("name"))
    {
        log<level::ERR>("Missing required group attribute",
                        entry("JSON=%s", jsonObj.dump().c_str()));
        throw std::runtime_error("Missing required group attribute");
    }

    // Get the group members' interface
    auto intf = jsonObj["interface"].get<std::string>();
    group.setInterface(intf);

    // Get the group members' property name
    auto prop = jsonObj["property"]["name"].get<std::string>();
    group.setProperty(prop);

    // Get the group members' data type
    if (jsonObj["property"].contains("type"))
    {
        std::optional<std::string> type =
            jsonObj["property"]["type"].get<std::string>();
        group.setType(type);
    }

    // Get the group members' expected value
    if (jsonObj["property"].contains("value"))
    {
        std::optional<PropertyVariantType> value =
            getJsonValue(jsonObj["property"]["value"]);
        group.setValue(value);
    }
}

void Event::setGroups(const json& jsonObj,
                      const std::vector<std::string>& profiles,
                      std::vector<Group>& groups)
{
    if (jsonObj.contains("groups"))
    {
        auto& availGroups = getAllGroups();
        for (const auto& jsonGrp : jsonObj["groups"])
        {
            if (!jsonGrp.contains("name"))
            {
                auto msg = std::format("Missing required group name attribute");
                log<level::ERR>(msg.c_str(),
                                entry("JSON=%s", jsonGrp.dump().c_str()));
                throw std::runtime_error(msg.c_str());
            }

            configKey eventProfile =
                std::make_pair(jsonGrp["name"].get<std::string>(), profiles);
            auto grpEntry = std::find_if(
                availGroups.begin(), availGroups.end(),
                [&eventProfile](const auto& grp) {
                    return Manager::inConfig(grp.first, eventProfile);
                });
            if (grpEntry != availGroups.end())
            {
                auto group = Group(*grpEntry->second);
                configGroup(group, jsonGrp);
                groups.emplace_back(group);
            }
        }
    }
}

void Event::setActions(const json& jsonObj)
{
    for (const auto& jsonAct : jsonObj["actions"])
    {
        if (!jsonAct.contains("name"))
        {
            log<level::ERR>("Missing required event action name",
                            entry("JSON=%s", jsonAct.dump().c_str()));
            throw std::runtime_error("Missing required event action name");
        }

        // Determine list of zones action should be run against
        std::vector<std::reference_wrapper<Zone>> actionZones;
        if (!jsonAct.contains("zones"))
        {
            // No zones configured on the action results in the action running
            // against all zones matching the event's active profiles
            for (const auto& zone : _zones)
            {
                configKey eventProfile =
                    std::make_pair(zone.second->getName(), _profiles);
                auto zoneEntry = std::find_if(
                    _zones.begin(), _zones.end(),
                    [&eventProfile](const auto& z) {
                        return Manager::inConfig(z.first, eventProfile);
                    });
                if (zoneEntry != _zones.end())
                {
                    actionZones.emplace_back(*zoneEntry->second);
                }
            }
        }
        else
        {
            // Zones configured on the action result in the action only running
            // against those zones if they match the event's active profiles
            for (const auto& jsonZone : jsonAct["zones"])
            {
                configKey eventProfile =
                    std::make_pair(jsonZone.get<std::string>(), _profiles);
                auto zoneEntry = std::find_if(
                    _zones.begin(), _zones.end(),
                    [&eventProfile](const auto& z) {
                        return Manager::inConfig(z.first, eventProfile);
                    });
                if (zoneEntry != _zones.end())
                {
                    actionZones.emplace_back(*zoneEntry->second);
                }
            }
        }
        if (actionZones.empty())
        {
            log<level::DEBUG>(
                std::format("No zones configured for event {}'s action {} "
                            "based on the active profile(s)",
                            getName(), jsonAct["name"].get<std::string>())
                    .c_str());
        }

        // Action specific groups, if any given, will override the use of event
        // groups in the action(s)
        std::vector<Group> actionGroups;
        setGroups(jsonAct, _profiles, actionGroups);
        if (!actionGroups.empty())
        {
            // Create the action for the event using the action's groups
            auto actObj = ActionFactory::getAction(
                jsonAct["name"].get<std::string>(), jsonAct,
                std::move(actionGroups), std::move(actionZones));
            if (actObj)
            {
                actObj->setEventName(_name);
                _actions.emplace_back(std::move(actObj));
            }
        }
        else
        {
            // Create the action for the event using the event's groups
            auto actObj = ActionFactory::getAction(
                jsonAct["name"].get<std::string>(), jsonAct, _groups,
                std::move(actionZones));
            if (actObj)
            {
                actObj->setEventName(_name);
                _actions.emplace_back(std::move(actObj));
            }
        }

        if (actionGroups.empty() && _groups.empty())
        {
            log<level::DEBUG>(
                std::format("No groups configured for event {}'s action {} "
                            "based on the active profile(s)",
                            getName(), jsonAct["name"].get<std::string>())
                    .c_str());
        }
    }
}

void Event::setTriggers(const json& jsonObj)
{
    if (!jsonObj.contains("triggers"))
    {
        log<level::ERR>("Missing required event triggers list",
                        entry("JSON=%s", jsonObj.dump().c_str()));
        throw std::runtime_error("Missing required event triggers list");
    }
    for (const auto& jsonTrig : jsonObj["triggers"])
    {
        if (!jsonTrig.contains("class"))
        {
            log<level::ERR>("Missing required event trigger class",
                            entry("JSON=%s", jsonTrig.dump().c_str()));
            throw std::runtime_error("Missing required event trigger class");
        }
        // The class of trigger used to run the event actions
        auto tClass = jsonTrig["class"].get<std::string>();
        std::transform(tClass.begin(), tClass.end(), tClass.begin(), tolower);
        auto trigFunc = trigger::triggers.find(tClass);
        if (trigFunc != trigger::triggers.end())
        {
            _triggers.emplace_back(
                trigFunc->first,
                trigFunc->second(jsonTrig, getName(), _actions));
        }
        else
        {
            // Construct list of available triggers
            auto availTrigs = std::accumulate(
                std::next(trigger::triggers.begin()), trigger::triggers.end(),
                trigger::triggers.begin()->first, [](auto list, auto trig) {
                    return std::move(list) + ", " + trig.first;
                });
            log<level::ERR>(
                std::format("Trigger '{}' is not recognized", tClass).c_str(),
                entry("AVAILABLE_TRIGGERS=%s", availTrigs.c_str()));
            throw std::runtime_error("Unsupported trigger class name given");
        }
    }
}

json Event::dump() const
{
    json actionData;
    std::for_each(_actions.begin(), _actions.end(),
                  [&actionData](const auto& action) {
                      actionData[action->getUniqueName()] = action->dump();
                  });

    std::vector<std::string> groupData;
    std::for_each(_groups.begin(), _groups.end(),
                  [&groupData](const auto& group) {
                      groupData.push_back(group.getName());
                  });

    json eventData;
    eventData["groups"] = groupData;
    eventData["actions"] = actionData;

    return eventData;
}

} // namespace phosphor::fan::control::json
