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

#include <phosphor-logging/log.hpp>

#include <algorithm>

namespace phosphor
{
namespace fan
{
namespace monitor
{

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

Fan::Fan(Mode mode, sdbusplus::bus::bus& bus, const sdeventplus::Event& event,
         std::unique_ptr<trust::Manager>& trust, const FanDefinition& def,
         System& system) :
    _bus(bus),
    _name(std::get<fanNameField>(def)),
    _deviation(std::get<fanDeviationField>(def)),
    _numSensorFailsForNonFunc(std::get<numSensorFailsForNonfuncField>(def)),
    _trustManager(trust),
#ifdef MONITOR_USE_JSON
    _monitorDelay(std::get<monitorStartDelayField>(def)),
    _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(std::get<fanMissingErrDelayField>(def)),
    _setFuncOnPresent(std::get<funcOnPresentField>(def))
{
    // Setup tach sensors for monitoring
    auto& sensors = std::get<sensorListField>(def);
    for (auto& s : sensors)
    {
        _sensors.emplace_back(std::make_shared<TachSensor>(
            mode, bus, *this, std::get<sensorNameField>(s),
            std::get<hasTargetField>(s), std::get<funcDelay>(def),
            std::get<targetInterfaceField>(s), std::get<factorField>(s),
            std::get<offsetField>(s), std::get<methodField>(def),
            std::get<thresholdField>(s), std::get<ignoreAboveMaxField>(s),
            std::get<timeoutField>(def),
            std::get<nonfuncRotorErrDelayField>(def),
            std::get<countIntervalField>(def), 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(
                fmt::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::message& 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(fmt::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) {
        if (_present)
        {
            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.
                getLogger().log(fmt::format(
                    "Monitoring starting but {} sensor value not on D-Bus",
                    sensor->name()));

                sensor->setFunctional(false);

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

                _system.fanStatusChange(*this);
            }
        }
    });
}

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);

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

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

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

    sensor.setFunctional(!sensor.functional());
    getLogger().log(
        fmt::format("Setting tach sensor {} functional state to {}. "
                    "[target = {}, input = {}, allowed range = ({} - {})]",
                    sensor.name(), sensor.functional(), sensor.getTarget(),
                    sensor.getInput(), range.first, rangeMax));

    // 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(fmt::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(fmt::format("Setting fan {} to nonfunctional, "
                                        "number of nonfunctional sensors = {}",
                                        _name, numNonFuncSensors));
            updateInventory(false);
        }
    }

    _system.fanStatusChange(*this);
}

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(
            fmt::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::message& 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(
            fmt::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(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(fmt::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(
                fmt::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
