/**
 * 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 <fmt/format.h>

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

#include <algorithm>
#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& trigger : _triggers)
    {
        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 = fmt::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>(
                fmt::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)
            {
                _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)
            {
                _actions.emplace_back(std::move(actObj));
            }
        }

        if (actionGroups.empty() && _groups.empty())
        {
            log<level::DEBUG>(
                fmt::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->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>(
                fmt::format("Trigger '{}' is not recognized", tClass).c_str(),
                entry("AVAILABLE_TRIGGERS=%s", availTrigs.c_str()));
            throw std::runtime_error("Unsupported trigger class name given");
        }
    }
}

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