/**
 * 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 "sdbusplus.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;

Fan::Fan(Mode mode, sdbusplus::bus::bus& bus, const sdeventplus::Event& event,
         std::unique_ptr<trust::Manager>& trust, const FanDefinition& def) :
    _bus(bus),
    _name(std::get<fanNameField>(def)),
    _deviation(std::get<fanDeviationField>(def)),
    _numSensorFailsForNonFunc(std::get<numSensorFailsForNonfuncField>(def)),
    _trustManager(trust)
{
    // Start from a known state of functional
    updateInventory(true);

    // Setup tach sensors for monitoring
    auto& sensors = std::get<sensorListField>(def);
    for (auto& s : sensors)
    {
        try
        {
            _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<timeoutField>(def), event));

            _trustManager->registerSensor(_sensors.back());
        }
        catch (InvalidSensorError& e)
        {
            // Count the number of failed tach sensors
            if (++_numFailedSensor >= _numSensorFailsForNonFunc)
            {
                // Mark associated fan as nonfunctional
                updateInventory(false);
            }
        }
    }

    // Check current tach state when entering monitor mode
    if (mode != Mode::init)
    {
        // The TachSensors will now have already read the input
        // and target values, so check them.
        tachChanged();
    }
}

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

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

    // 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())
        {
            // Start nonfunctional timer if not already running
            sensor.startTimer(TimerMode::nonfunc);
        }
    }
    else
    {
        if (sensor.functional())
        {
            sensor.stopTimer();
        }
        else
        {
            // Start functional timer if not already running
            sensor.startTimer(TimerMode::func);
        }
    }
}

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

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

    return (numFailed >= _numSensorFailsForNonFunc);
}

bool Fan::outOfRange(const TachSensor& sensor)
{
    auto actual = static_cast<uint64_t>(sensor.getInput());
    auto target = sensor.getTarget();
    auto factor = sensor.getFactor();
    auto offset = sensor.getOffset();

    uint64_t min = target * (100 - _deviation) / 100;
    uint64_t max = target * (100 + _deviation) / 100;

    // TODO: openbmc/openbmc#2937 enhance this function
    // either by making it virtual, or by predefining different
    // outOfRange ops and selecting by yaml config
    min = min * factor + offset;
    max = max * factor + offset;
    if ((actual < min) || (actual > max))
    {
        return true;
    }

    return false;
}

void Fan::timerExpired(TachSensor& sensor)
{
    sensor.setFunctional(!sensor.functional());

    // If the fan was nonfunctional and enough sensors are now OK,
    // the fan can go back to functional
    if (!_functional && !tooManySensorsNonfunctional())
    {
        log<level::INFO>(
            fmt::format("Setting fan {} back to functional", _name).c_str());

        updateInventory(true);
    }

    // If the fan is currently functional, but too many
    // contained sensors are now nonfunctional, update
    // the whole fan nonfunctional.
    if (_functional && tooManySensorsNonfunctional())
    {
        log<level::ERR>(fmt::format("Setting fan {} to nonfunctional "
                                    "Sensor: {} "
                                    "Actual speed: {} "
                                    "Target speed: {}",
                                    _name, sensor.name(), sensor.getInput(),
                                    sensor.getTarget())
                            .c_str());

        updateInventory(false);
    }
}

void Fan::updateInventory(bool functional)
{
    auto objectMap =
        util::getObjMap<bool>(_name, util::OPERATIONAL_STATUS_INTF,
                              util::FUNCTIONAL_PROPERTY, functional);
    auto response = util::SDBusPlus::lookupAndCallMethod(
        _bus, util::INVENTORY_PATH, util::INVENTORY_INTF, "Notify", objectMap);
    if (response.is_method_error())
    {
        log<level::ERR>("Error in Notify call to update inventory");
        return;
    }

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

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