/**
 * 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 "service_indicators.hpp"

#include <fmt/format.h>

#include <bitset>
#include <phosphor-logging/log.hpp>

namespace openpower::pels::service_indicators
{

using namespace phosphor::logging;

static constexpr auto platformSaiLedGroup =
    "/xyz/openbmc_project/led/groups/platform_system_attention_indicator";

std::unique_ptr<Policy> getPolicy(const DataInterfaceBase& dataIface)
{
    // At the moment there is just one type of policy.
    return std::make_unique<LightPath>(dataIface);
}

bool LightPath::ignore(const PEL& pel) const
{
    auto creator = pel.privateHeader().creatorID();

    // Don't ignore serviceable BMC or hostboot errors
    if ((static_cast<CreatorID>(creator) == CreatorID::openBMC) ||
        (static_cast<CreatorID>(creator) == CreatorID::hostboot))
    {
        std::bitset<16> actionFlags{pel.userHeader().actionFlags()};
        if (actionFlags.test(serviceActionFlagBit))
        {
            return false;
        }
    }

    return true;
}

void LightPath::activate(const PEL& pel)
{
    if (ignore(pel))
    {
        return;
    }

    // Now that we've gotten this far, we'll need to turn on
    // the system attention indicator if we don't find other
    // indicators to turn on.
    bool sai = true;
    auto src = pel.primarySRC();
    const auto& calloutsObj = (*src)->callouts();

    if (calloutsObj && !calloutsObj->callouts().empty())
    {
        const auto& callouts = calloutsObj->callouts();

        // From the callouts, find the location codes whose
        // LEDs need to be turned on.
        auto locCodes = getLocationCodes(callouts);
        if (!locCodes.empty())
        {
            // Find the inventory paths for those location codes.
            auto paths = getInventoryPaths(locCodes);
            if (!paths.empty())
            {
                setNotFunctional(paths);
                createCriticalAssociation(paths);
                sai = false;
            }
        }
    }

    if (sai)
    {
        try
        {
            _dataIface.assertLEDGroup(platformSaiLedGroup, true);
        }
        catch (const std::exception& e)
        {
            log<level::ERR>(
                fmt::format("Failed to assert platform SAI LED group: {}",
                            e.what())
                    .c_str());
        }
    }
}

std::vector<std::string> LightPath::getLocationCodes(
    const std::vector<std::unique_ptr<src::Callout>>& callouts) const
{
    std::vector<std::string> locCodes;
    bool firstCallout = true;
    uint8_t firstCalloutPriority;

    // Collect location codes for the first group of callouts,
    // where a group can be:
    //  * a single medium priority callout
    //  * one or more high priority callouts
    //  * one or more medium group a priority callouts
    //
    // All callouts in the group must be hardware callouts.

    for (const auto& callout : callouts)
    {
        if (firstCallout)
        {
            firstCallout = false;

            firstCalloutPriority = callout->priority();

            // If the first callout is High, Medium, or Medium
            // group A, and is a hardware callout, then we
            // want it.
            if (isRequiredPriority(firstCalloutPriority) &&
                isHardwareCallout(*callout))
            {
                locCodes.push_back(callout->locationCode());
            }
            else
            {
                break;
            }

            // By definition a medium priority callout can't be part
            // of a group, so no need to look for more.
            if (static_cast<CalloutPriority>(firstCalloutPriority) ==
                CalloutPriority::medium)
            {
                break;
            }
        }
        else
        {
            // Only continue while the callouts are the same
            // priority as the first callout.
            if (callout->priority() != firstCalloutPriority)
            {
                break;
            }

            // If any callout in the group isn't a hardware callout,
            // then don't light up any LEDs at all.
            if (!isHardwareCallout(*callout))
            {
                locCodes.clear();
                break;
            }

            locCodes.push_back(callout->locationCode());
        }
    }

    return locCodes;
}

bool LightPath::isRequiredPriority(uint8_t priority) const
{
    auto calloutPriority = static_cast<CalloutPriority>(priority);
    return (calloutPriority == CalloutPriority::high) ||
           (calloutPriority == CalloutPriority::medium) ||
           (calloutPriority == CalloutPriority::mediumGroupA);
}

bool LightPath::isHardwareCallout(const src::Callout& callout) const
{
    const auto& fruIdentity = callout.fruIdentity();
    if (fruIdentity)
    {
        return (callout.locationCodeSize() != 0) &&
               ((fruIdentity->failingComponentType() ==
                 src::FRUIdentity::hardwareFRU) ||
                (fruIdentity->failingComponentType() ==
                 src::FRUIdentity::symbolicFRUTrustedLocCode));
    }

    return false;
}

std::vector<std::string> LightPath::getInventoryPaths(
    const std::vector<std::string>& locationCodes) const
{
    std::vector<std::string> paths;

    for (const auto& locCode : locationCodes)
    {
        try
        {
            auto inventoryPath =
                _dataIface.getInventoryFromLocCode(locCode, 0, true);
            paths.push_back(std::move(inventoryPath));
        }
        catch (const std::exception& e)
        {
            log<level::ERR>(fmt::format("Could not get inventory path for "
                                        "location code {} ({}).",
                                        locCode, e.what())
                                .c_str());

            // Unless we can set the LEDs for all FRUs, we can't turn
            // on any of them, so clear the list and quit.
            paths.clear();
            break;
        }
    }

    return paths;
}

void LightPath::setNotFunctional(
    const std::vector<std::string>& inventoryPaths) const
{
    for (const auto& path : inventoryPaths)
    {
        try
        {
            _dataIface.setFunctional(path, false);
        }
        catch (const std::exception& e)
        {
            log<level::INFO>(
                fmt::format("Could not write Functional property on {} ({})",
                            path, e.what())
                    .c_str());
        }
    }
}

void LightPath::createCriticalAssociation(
    const std::vector<std::string>& inventoryPaths) const
{
    for (const auto& path : inventoryPaths)
    {
        try
        {
            _dataIface.setCriticalAssociation(path);
        }
        catch (const std::exception& e)
        {
            log<level::INFO>(
                fmt::format(
                    "Could not set critical association on object path {} ({})",
                    path, e.what())
                    .c_str());
        }
    }
}

} // namespace openpower::pels::service_indicators
