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

#include "fan.hpp"
#include "get_power_state.hpp"
#include "psensor.hpp"

#include <phosphor-logging/log.hpp>

#include <algorithm>

namespace phosphor
{
namespace fan
{
namespace presence
{

using namespace std::chrono_literals;
static const auto powerOnDelayTime = 5s;

AnyOf::AnyOf(const Fan& fan,
             const std::vector<std::reference_wrapper<PresenceSensor>>& s) :
    RedundancyPolicy(fan),
    state(), _powerState(getPowerStateObject()),
    _powerOnDelayTimer(sdeventplus::Event::get_default(),
                       std::bind(&AnyOf::delayedAfterPowerOn, this)),
    _powerOn(false)
{
    for (auto& sensor : s)
    {
        state.emplace_back(sensor, false, false);
    }

    _powerState->addCallback(
        std::get<1>(fan) + "-anyOf",
        std::bind(&AnyOf::powerStateChanged, this, std::placeholders::_1));

    // If power is already on, give the fans some time to spin up
    // before considering power to actually be on.
    if (_powerState->isPowerOn())
    {
        _powerOnDelayTimer.restartOnce(powerOnDelayTime);
    }
}

void AnyOf::stateChanged(bool present, PresenceSensor& sensor)
{
    // Find the sensor that changed state.
    auto sit =
        std::find_if(state.begin(), state.end(), [&sensor](const auto& s) {
            return std::get<sensorPos>(s).get() == sensor;
        });
    if (sit != state.end())
    {
        auto origState =
            std::any_of(state.begin(), state.end(),
                        [](const auto& s) { return std::get<presentPos>(s); });

        // Update our cache of the sensors state and re-evaluate.
        std::get<presentPos>(*sit) = present;
        auto newState =
            std::any_of(state.begin(), state.end(),
                        [](const auto& s) { return std::get<presentPos>(s); });
        setPresence(fan, newState);

        // At least 1 sensor said a fan was present, check if any disagree.
        if (newState)
        {
            if (!origState)
            {
                // Fan plug detected, re-enable conflict logging
                std::for_each(state.begin(), state.end(), [](auto& s) {
                    std::get<conflictPos>(s) = false;
                });
            }

            checkSensorConflicts();
        }
    }
}

void AnyOf::monitor()
{
    // Start all sensors in the anyof redundancy set.

    for (auto& s : state)
    {
        auto& sensor = std::get<sensorPos>(s);
        std::get<presentPos>(s) = sensor.get().start();
    }

    auto present = std::any_of(state.begin(), state.end(), [](const auto& s) {
        return std::get<presentPos>(s);
    });
    setPresence(fan, present);

    // At least one of the contained methods indicated present,
    // so check that they all agree.
    if (present)
    {
        checkSensorConflicts();
    }
}

void AnyOf::checkSensorConflicts()
{
    if (!isPowerOn())
    {
        return;
    }

    // If at least one, but not all, sensors indicate present, then
    // tell the not present ones to log a conflict if not already done.
    if (std::any_of(
            state.begin(), state.end(),
            [this](const auto& s) { return std::get<presentPos>(s); }) &&
        !std::all_of(state.begin(), state.end(),
                     [this](const auto& s) { return std::get<presentPos>(s); }))
    {
        for (auto& [sensor, present, conflict] : state)
        {
            if (!present && !conflict)
            {
                sensor.get().logConflict(invNamespace + std::get<1>(fan));
                conflict = true;
            }
        }
    }
}

void AnyOf::powerStateChanged(bool powerOn)
{
    if (powerOn)
    {
        // Clear the conflict state from last time
        std::for_each(state.begin(), state.end(), [](auto& state) {
            std::get<conflictPos>(state) = false;
        });

        // Wait to give the fans time to start spinning before
        // considering power actually on.
        _powerOnDelayTimer.restartOnce(powerOnDelayTime);
    }
    else
    {
        _powerOn = false;

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

void AnyOf::delayedAfterPowerOn()
{
    _powerOn = true;
    checkSensorConflicts();
}

} // namespace presence
} // namespace fan
} // namespace phosphor
