/**
 * Copyright © 2022 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 "fan.hpp"

#include "logging.hpp"
#include "sdbusplus.hpp"
#include "system.hpp"
#include "types.hpp"
#include "utility.hpp"

#include <phosphor-logging/log.hpp>

#include <format>

namespace phosphor
{
namespace fan
{
namespace monitor
{

using namespace phosphor::logging;
using namespace sdbusplus::bus::match;

Fan::Fan(Mode mode, sdbusplus::bus_t& bus, const sdeventplus::Event& event,
         std::unique_ptr<trust::Manager>& trust, const FanDefinition& def,
         System& system) :
    _bus(bus), _name(def.name), _deviation(def.deviation),
    _upperDeviation(def.upperDeviation),
    _numSensorFailsForNonFunc(def.numSensorFailsForNonfunc),
    _trustManager(trust),
#ifdef MONITOR_USE_JSON
    _monitorDelay(def.monitorStartDelay),
    _monitorTimer(event, std::bind(std::mem_fn(&Fan::startMonitor), this)),
#endif
    _system(system),
    _presenceMatch(bus,
                   rules::propertiesChanged(util::INVENTORY_PATH + _name,
                                            util::INV_ITEM_IFACE),
                   std::bind(std::mem_fn(&Fan::presenceChanged), this,
                             std::placeholders::_1)),
    _presenceIfaceAddedMatch(
        bus,
        rules::interfacesAdded() +
            rules::argNpath(0, util::INVENTORY_PATH + _name),
        std::bind(std::mem_fn(&Fan::presenceIfaceAdded), this,
                  std::placeholders::_1)),
    _fanMissingErrorDelay(def.fanMissingErrDelay),
    _setFuncOnPresent(def.funcOnPresent)
{
    // Setup tach sensors for monitoring
    for (const auto& s : def.sensorList)
    {
        _sensors.emplace_back(std::make_shared<TachSensor>(
            mode, bus, *this, s.name, s.hasTarget, def.funcDelay,
            s.targetInterface, s.targetPath, s.factor, s.offset, def.method,
            s.threshold, s.ignoreAboveMax, def.timeout,
            def.nonfuncRotorErrDelay, def.countInterval, event));

        _trustManager->registerSensor(_sensors.back());
    }

    bool functionalState =
        (_numSensorFailsForNonFunc == 0) ||
        (countNonFunctionalSensors() < _numSensorFailsForNonFunc);

    if (updateInventory(functionalState) && !functionalState)
    {
        // the inventory update threw an exception, possibly because D-Bus
        // wasn't ready. Try to update sensors back to functional to avoid a
        // false-alarm. They will be updated again from subscribing to the
        // properties-changed event

        for (auto& sensor : _sensors)
            sensor->setFunctional(true);
    }

#ifndef MONITOR_USE_JSON
    // Check current tach state when entering monitor mode
    if (mode != Mode::init)
    {
        _monitorReady = true;

        // The TachSensors will now have already read the input
        // and target values, so check them.
        tachChanged();
    }
#else
    if (_system.isPowerOn())
    {
        _monitorTimer.restartOnce(std::chrono::seconds(_monitorDelay));
    }
#endif

    if (_fanMissingErrorDelay)
    {
        _fanMissingErrorTimer = std::make_unique<
            sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>(
            event, std::bind(&System::fanMissingErrorTimerExpired, &system,
                             std::ref(*this)));
    }

    try
    {
        _present = util::SDBusPlus::getProperty<bool>(
            util::INVENTORY_PATH + _name, util::INV_ITEM_IFACE, "Present");

        if (!_present)
        {
            getLogger().log(
                std::format("On startup, fan {} is missing", _name));
            if (_system.isPowerOn() && _fanMissingErrorTimer)
            {
                _fanMissingErrorTimer->restartOnce(
                    std::chrono::seconds{*_fanMissingErrorDelay});
            }
        }
    }
    catch (const util::DBusServiceError& e)
    {
        // This could happen on the first BMC boot if the presence
        // detect app hasn't started yet and there isn't an inventory
        // cache yet.
    }
}

void Fan::presenceIfaceAdded(sdbusplus::message_t& msg)
{
    sdbusplus::message::object_path path;
    std::map<std::string, std::map<std::string, std::variant<bool>>> interfaces;

    msg.read(path, interfaces);

    auto properties = interfaces.find(util::INV_ITEM_IFACE);
    if (properties == interfaces.end())
    {
        return;
    }

    auto property = properties->second.find("Present");
    if (property == properties->second.end())
    {
        return;
    }

    _present = std::get<bool>(property->second);

    if (!_present)
    {
        getLogger().log(std::format(
            "New fan {} interface added and fan is not present", _name));
        if (_system.isPowerOn() && _fanMissingErrorTimer)
        {
            _fanMissingErrorTimer->restartOnce(
                std::chrono::seconds{*_fanMissingErrorDelay});
        }
    }

    _system.fanStatusChange(*this);
}

void Fan::startMonitor()
{
    _monitorReady = true;

    std::for_each(_sensors.begin(), _sensors.end(), [this](auto& sensor) {
        try
        {
            // Force a getProperty call to check if the tach sensor is
            // on D-Bus.  If it isn't, now set it to nonfunctional.
            // This isn't done earlier so that code watching for
            // nonfunctional tach sensors doesn't take actions before
            // those sensors show up on D-Bus.
            sensor->updateTachAndTarget();
            tachChanged(*sensor);
        }
        catch (const util::DBusServiceError& e)
        {
            // The tach property still isn't on D-Bus. Ensure
            // sensor is nonfunctional, but skip creating an
            // error for it since it isn't a fan problem.
            getLogger().log(std::format(
                "Monitoring starting but {} sensor value not on D-Bus",
                sensor->name()));

            sensor->setFunctional(false, true);

            if (_numSensorFailsForNonFunc)
            {
                if (_functional &&
                    (countNonFunctionalSensors() >= _numSensorFailsForNonFunc))
                {
                    updateInventory(false);
                }
            }

            // At this point, don't start any power off actions due
            // to missing sensors.  Let something else handle that
            // policy.
            _system.fanStatusChange(*this, true);
        }
    });
}

void Fan::tachChanged()
{
    if (_monitorReady)
    {
        for (auto& s : _sensors)
        {
            tachChanged(*s);
        }
    }
}

void Fan::tachChanged(TachSensor& sensor)
{
    if (!_system.isPowerOn() || !_monitorReady)
    {
        return;
    }

    if (_trustManager->active())
    {
        if (!_trustManager->checkTrust(sensor))
        {
            return;
        }
    }

    // If the error checking method is 'count', if a tach change leads
    // to an out of range sensor the count timer will take over in calling
    // process() until the sensor is healthy again.
    if (!sensor.countTimerRunning())
    {
        process(sensor);
    }
}

void Fan::countTimerExpired(TachSensor& sensor)
{
    if (_trustManager->active() && !_trustManager->checkTrust(sensor))
    {
        return;
    }
    process(sensor);
}

void Fan::process(TachSensor& sensor)
{
    // If this sensor is out of range at this moment, start
    // its timer, at the end of which the inventory
    // for the fan may get updated to not functional.

    // If this sensor is OK, put everything back into a good state.

    if (outOfRange(sensor))
    {
        if (sensor.functional())
        {
            switch (sensor.getMethod())
            {
                case MethodMode::timebased:
                    // Start nonfunctional timer if not already running
                    sensor.startTimer(TimerMode::nonfunc);
                    break;
                case MethodMode::count:

                    if (!sensor.countTimerRunning())
                    {
                        sensor.startCountTimer();
                    }
                    sensor.setCounter(true);
                    if (sensor.getCounter() >= sensor.getThreshold())
                    {
                        updateState(sensor);
                    }
                    break;
            }
        }
    }
    else
    {
        switch (sensor.getMethod())
        {
            case MethodMode::timebased:
                if (sensor.functional())
                {
                    if (sensor.timerRunning())
                    {
                        sensor.stopTimer();
                    }
                }
                else
                {
                    // Start functional timer if not already running
                    sensor.startTimer(TimerMode::func);
                }
                break;
            case MethodMode::count:
                sensor.setCounter(false);
                if (sensor.getCounter() == 0)
                {
                    if (!sensor.functional())
                    {
                        updateState(sensor);
                    }

                    sensor.stopCountTimer();
                }
                break;
        }
    }
}

uint64_t Fan::findTargetSpeed()
{
    uint64_t target = 0;
    // The sensor doesn't support a target,
    // so get it from another sensor.
    auto s = std::find_if(_sensors.begin(), _sensors.end(), [](const auto& s) {
        return s->hasTarget();
    });

    if (s != _sensors.end())
    {
        target = (*s)->getTarget();
    }

    return target;
}

size_t Fan::countNonFunctionalSensors() const
{
    return std::count_if(_sensors.begin(), _sensors.end(), [](const auto& s) {
        return !s->functional();
    });
}

bool Fan::outOfRange(const TachSensor& sensor)
{
    if (!sensor.hasOwner())
    {
        return true;
    }

    auto actual = static_cast<uint64_t>(sensor.getInput());
    auto range = sensor.getRange(_deviation, _upperDeviation);

    return ((actual < range.first) ||
            (range.second && actual > range.second.value()));
}

void Fan::updateState(TachSensor& sensor)
{
    if (!_system.isPowerOn())
    {
        return;
    }

    auto range = sensor.getRange(_deviation, _upperDeviation);
    std::string rangeMax = "NoMax";
    if (range.second)
    {
        rangeMax = std::to_string(range.second.value());
    }

    // Skip starting the error timer if the sensor
    // isn't on D-Bus as this isn't a fan hardware problem.
    sensor.setFunctional(!sensor.functional(), !sensor.hasOwner());

    getLogger().log(std::format(
        "Setting tach sensor {} functional state to {}. "
        "[target = {}, actual = {}, allowed range = ({} - {}) "
        "owned = {}]",
        sensor.name(), sensor.functional(), sensor.getTarget(),
        sensor.getInput(), range.first, rangeMax, sensor.hasOwner()));

    // A zero value for _numSensorFailsForNonFunc means we aren't dealing
    // with fan FRU functional status, only sensor functional status.
    if (_numSensorFailsForNonFunc)
    {
        auto numNonFuncSensors = countNonFunctionalSensors();
        // If the fan was nonfunctional and enough sensors are now OK,
        // the fan can be set to functional as long as `set_func_on_present` was
        // not set
        if (!_setFuncOnPresent && !_functional &&
            !(numNonFuncSensors >= _numSensorFailsForNonFunc))
        {
            getLogger().log(std::format("Setting fan {} to functional, number "
                                        "of nonfunctional sensors = {}",
                                        _name, numNonFuncSensors));
            updateInventory(true);
        }

        // If the fan is currently functional, but too many
        // contained sensors are now nonfunctional, update
        // the fan to nonfunctional.
        if (_functional && (numNonFuncSensors >= _numSensorFailsForNonFunc))
        {
            getLogger().log(std::format("Setting fan {} to nonfunctional, "
                                        "number of nonfunctional sensors = {}",
                                        _name, numNonFuncSensors));
            updateInventory(false);
        }
    }

    // Skip the power off rule checks if the sensor isn't
    // on D-Bus so a running system isn't shutdown.
    _system.fanStatusChange(*this, !sensor.hasOwner());
}

bool Fan::updateInventory(bool functional)
{
    bool dbusError = false;

    try
    {
        auto objectMap =
            util::getObjMap<bool>(_name, util::OPERATIONAL_STATUS_INTF,
                                  util::FUNCTIONAL_PROPERTY, functional);

        auto response = util::SDBusPlus::callMethod(
            _bus, util::INVENTORY_SVC, util::INVENTORY_PATH,
            util::INVENTORY_INTF, "Notify", objectMap);

        if (response.is_method_error())
        {
            log<level::ERR>("Error in Notify call to update inventory");

            dbusError = true;
        }
    }
    catch (const util::DBusError& e)
    {
        dbusError = true;

        getLogger().log(
            std::format("D-Bus Exception reading/updating inventory : {}",
                        e.what()),
            Logger::error);
    }

    // This will always track the current state of the inventory.
    _functional = functional;

    return dbusError;
}

void Fan::presenceChanged(sdbusplus::message_t& msg)
{
    std::string interface;
    std::map<std::string, std::variant<bool>> properties;

    msg.read(interface, properties);

    auto presentProp = properties.find("Present");
    if (presentProp != properties.end())
    {
        _present = std::get<bool>(presentProp->second);

        getLogger().log(
            std::format("Fan {} presence state change to {}", _name, _present));

        if (_present && _setFuncOnPresent)
        {
            updateInventory(true);
            std::for_each(_sensors.begin(), _sensors.end(), [](auto& sensor) {
                sensor->setFunctional(true);
                sensor->resetMethod();
            });
        }

        _system.fanStatusChange(*this);

        if (_fanMissingErrorDelay)
        {
            if (!_present && _system.isPowerOn())
            {
                _fanMissingErrorTimer->restartOnce(
                    std::chrono::seconds{*_fanMissingErrorDelay});
            }
            else if (_present && _fanMissingErrorTimer->isEnabled())
            {
                _fanMissingErrorTimer->setEnabled(false);
            }
        }
    }
}

void Fan::sensorErrorTimerExpired(const TachSensor& sensor)
{
    if (_present && _system.isPowerOn())
    {
        _system.sensorErrorTimerExpired(*this, sensor);
    }
}

void Fan::powerStateChanged([[maybe_unused]] bool powerStateOn)
{
#ifdef MONITOR_USE_JSON
    if (powerStateOn)
    {
        _monitorTimer.restartOnce(std::chrono::seconds(_monitorDelay));

        _numSensorsOnDBusAtPowerOn = 0;

        std::for_each(_sensors.begin(), _sensors.end(), [this](auto& sensor) {
            try
            {
                // Force a getProperty call.  If sensor is on D-Bus,
                // then make sure it's functional.
                sensor->updateTachAndTarget();

                _numSensorsOnDBusAtPowerOn++;

                if (_present)
                {
                    // If not functional, set it back to functional.
                    if (!sensor->functional())
                    {
                        sensor->setFunctional(true);
                        _system.fanStatusChange(*this, true);
                    }

                    // Set the counters back to zero
                    if (sensor->getMethod() == MethodMode::count)
                    {
                        sensor->resetMethod();
                    }
                }
            }
            catch (const util::DBusError& e)
            {
                // Properties still aren't on D-Bus.  Let startMonitor()
                // deal with it, or maybe System::powerStateChanged() if
                // there aren't any sensors at all on D-Bus.
                getLogger().log(std::format(
                    "At power on, tach sensor {} value not on D-Bus",
                    sensor->name()));
            }
        });

        if (_present)
        {
            // If configured to change functional state on the fan itself,
            // Set it back to true now if necessary.
            if (_numSensorFailsForNonFunc)
            {
                if (!_functional &&
                    (countNonFunctionalSensors() < _numSensorFailsForNonFunc))
                {
                    updateInventory(true);
                }
            }
        }
        else
        {
            getLogger().log(
                std::format("At power on, fan {} is missing", _name));

            if (_fanMissingErrorTimer)
            {
                _fanMissingErrorTimer->restartOnce(
                    std::chrono::seconds{*_fanMissingErrorDelay});
            }
        }
    }
    else
    {
        _monitorReady = false;

        if (_monitorTimer.isEnabled())
        {
            _monitorTimer.setEnabled(false);
        }

        if (_fanMissingErrorTimer && _fanMissingErrorTimer->isEnabled())
        {
            _fanMissingErrorTimer->setEnabled(false);
        }

        std::for_each(_sensors.begin(), _sensors.end(), [](auto& sensor) {
            if (sensor->timerRunning())
            {
                sensor->stopTimer();
            }

            sensor->stopCountTimer();
        });
    }
#endif
}

} // namespace monitor
} // namespace fan
} // namespace phosphor
