/**
 * 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 <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,
             std::unique_ptr<EEPROMDevice> e) :
    RedundancyPolicy(fan, std::move(e)), 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);

        if (eepromDevice && (newState != origState))
        {
            if (newState)
            {
                eepromDevice->bind();
            }
            else
            {
                eepromDevice->unbind();
            }
        }

        // 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(),
                    [](const auto& s) { return std::get<presentPos>(s); }) &&
        !std::all_of(state.begin(), state.end(),
                     [](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
