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

#include "elog-errors.hpp"
#include "gpio.hpp"
#include "names_values.hpp"
#include "pmbus.hpp"
#include "utility.hpp"

#include <functional>
#include <org/open_power/Witherspoon/Fault/error.hpp>
#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/log.hpp>
#include <xyz/openbmc_project/Common/Device/error.hpp>
#include <xyz/openbmc_project/Software/Version/server.hpp>

namespace witherspoon
{
namespace power
{
namespace psu
{

using namespace phosphor::logging;
using namespace sdbusplus::org::open_power::Witherspoon::Fault::Error;
using namespace sdbusplus::xyz::openbmc_project::Common::Device::Error;
namespace version = sdbusplus::xyz::openbmc_project::Software::server;

constexpr auto ASSOCIATION_IFACE = "org.openbmc.Association";
constexpr auto LOGGING_IFACE = "xyz.openbmc_project.Logging.Entry";
constexpr auto INVENTORY_IFACE = "xyz.openbmc_project.Inventory.Item";
constexpr auto POWER_IFACE = "org.openbmc.control.Power";
constexpr auto INVENTORY_MGR_IFACE = "xyz.openbmc_project.Inventory.Manager";
constexpr auto ASSET_IFACE = "xyz.openbmc_project.Inventory.Decorator.Asset";
constexpr auto VERSION_IFACE = "xyz.openbmc_project.Software.Version";

constexpr auto ENDPOINTS_PROP = "endpoints";
constexpr auto MESSAGE_PROP = "Message";
constexpr auto RESOLVED_PROP = "Resolved";
constexpr auto PRESENT_PROP = "Present";
constexpr auto SN_PROP = "SerialNumber";
constexpr auto PN_PROP = "PartNumber";
constexpr auto MODEL_PROP = "Model";
constexpr auto VERSION_PROP = "Version";
constexpr auto VERSION_PURPOSE_PROP = "Purpose";

constexpr auto INVENTORY_OBJ_PATH = "/xyz/openbmc_project/inventory";
constexpr auto POWER_OBJ_PATH = "/org/openbmc/control/power0";

constexpr auto SERIAL_NUMBER = "serial_number";
constexpr auto PART_NUMBER = "part_number";
constexpr auto FW_VERSION = "fw_version";
constexpr auto CCIN = "ccin";
constexpr auto INPUT_HISTORY = "input_history";

PowerSupply::PowerSupply(const std::string& name, size_t inst,
                         const std::string& objpath, const std::string& invpath,
                         sdbusplus::bus::bus& bus, const sdeventplus::Event& e,
                         std::chrono::seconds& t, std::chrono::seconds& p) :
    Device(name, inst),
    monitorPath(objpath), pmbusIntf(objpath),
    inventoryPath(INVENTORY_OBJ_PATH + invpath), bus(bus), presentInterval(p),
    presentTimer(e, std::bind([this]() {
                     // The hwmon path may have changed.
                     pmbusIntf.findHwmonDir();
                     this->present = true;

                     // Sync the INPUT_HISTORY data for all PSs
                     syncHistory();

                     // Update the inventory for the new device
                     updateInventory();
                 })),
    powerOnInterval(t),
    powerOnTimer(e, std::bind([this]() { this->powerOn = true; }))
{
    using namespace sdbusplus::bus;
    presentMatch = std::make_unique<match_t>(
        bus, match::rules::propertiesChanged(inventoryPath, INVENTORY_IFACE),
        [this](auto& msg) { this->inventoryChanged(msg); });
    // Get initial presence state.
    updatePresence();

    // Write the SN, PN, etc to the inventory
    updateInventory();

    // Subscribe to power state changes
    powerOnMatch = std::make_unique<match_t>(
        bus, match::rules::propertiesChanged(POWER_OBJ_PATH, POWER_IFACE),
        [this](auto& msg) { this->powerStateChanged(msg); });
    // Get initial power state.
    updatePowerState();
}

void PowerSupply::captureCmd(util::NamesValues& nv, const std::string& cmd,
                             witherspoon::pmbus::Type type)
{
    if (pmbusIntf.exists(cmd, type))
    {
        try
        {
            auto val = pmbusIntf.read(cmd, type);
            nv.add(cmd, val);
        }
        catch (std::exception& e)
        {
            log<level::INFO>("Unable to capture metadata",
                             entry("CMD=%s", cmd.c_str()));
        }
    }
}

void PowerSupply::analyze()
{
    using namespace witherspoon::pmbus;

    try
    {
        if (present)
        {
            std::uint16_t statusWord = 0;

            // Read the 2 byte STATUS_WORD value to check for faults.
            statusWord = pmbusIntf.read(STATUS_WORD, Type::Debug);
            readFail = 0;

            checkInputFault(statusWord);

            if (powerOn && (inputFault == 0) && !faultFound)
            {
                checkFanFault(statusWord);
                checkTemperatureFault(statusWord);
                checkOutputOvervoltageFault(statusWord);
                checkCurrentOutOverCurrentFault(statusWord);
                checkPGOrUnitOffFault(statusWord);
            }

            updateHistory();
        }
    }
    catch (ReadFailure& e)
    {
        if (readFail < FAULT_COUNT)
        {
            readFail++;
        }

        if (!readFailLogged && readFail >= FAULT_COUNT)
        {
            commit<ReadFailure>();
            readFailLogged = true;
        }
    }

    return;
}

void PowerSupply::inventoryChanged(sdbusplus::message::message& msg)
{
    std::string msgSensor;
    std::map<std::string, sdbusplus::message::variant<uint32_t, bool>> msgData;
    msg.read(msgSensor, msgData);

    // Check if it was the Present property that changed.
    auto valPropMap = msgData.find(PRESENT_PROP);
    if (valPropMap != msgData.end())
    {
        if (sdbusplus::message::variant_ns::get<bool>(valPropMap->second))
        {
            clearFaults();
            presentTimer.restartOnce(presentInterval);
        }
        else
        {
            present = false;
            presentTimer.setEnabled(false);

            // Clear out the now outdated inventory properties
            updateInventory();
        }
    }

    return;
}

void PowerSupply::updatePresence()
{
    // Use getProperty utility function to get presence status.
    std::string service = "xyz.openbmc_project.Inventory.Manager";
    util::getProperty(INVENTORY_IFACE, PRESENT_PROP, inventoryPath, service,
                      bus, this->present);
}

void PowerSupply::powerStateChanged(sdbusplus::message::message& msg)
{
    int32_t state = 0;
    std::string msgSensor;
    std::map<std::string, sdbusplus::message::variant<int32_t>> msgData;
    msg.read(msgSensor, msgData);

    // Check if it was the Present property that changed.
    auto valPropMap = msgData.find("state");
    if (valPropMap != msgData.end())
    {
        state =
            sdbusplus::message::variant_ns::get<int32_t>(valPropMap->second);

        // Power is on when state=1. Set the fault logged variables to false
        // and start the power on timer when the state changes to 1.
        if (state)
        {
            clearFaults();
            powerOnTimer.restartOnce(powerOnInterval);
        }
        else
        {
            powerOnTimer.setEnabled(false);
            powerOn = false;
        }
    }
}

void PowerSupply::updatePowerState()
{
    // When state = 1, system is powered on
    int32_t state = 0;

    try
    {
        auto service = util::getService(POWER_OBJ_PATH, POWER_IFACE, bus);

        // Use getProperty utility function to get power state.
        util::getProperty<int32_t>(POWER_IFACE, "state", POWER_OBJ_PATH,
                                   service, bus, state);

        if (state)
        {
            powerOn = true;
        }
        else
        {
            powerOn = false;
        }
    }
    catch (std::exception& e)
    {
        log<level::INFO>("Failed to get power state. Assuming it is off.");
        powerOn = false;
    }
}

void PowerSupply::checkInputFault(const uint16_t statusWord)
{
    using namespace witherspoon::pmbus;

    if ((inputFault < FAULT_COUNT) &&
        ((statusWord & status_word::INPUT_FAULT_WARN) ||
         (statusWord & status_word::VIN_UV_FAULT)))
    {
        if (inputFault == 0)
        {
            log<level::INFO>("INPUT or VIN_UV fault",
                             entry("STATUS_WORD=0x%04X", statusWord));
        }

        inputFault++;
    }
    else
    {
        if ((inputFault > 0) && !(statusWord & status_word::INPUT_FAULT_WARN) &&
            !(statusWord & status_word::VIN_UV_FAULT))
        {
            inputFault = 0;
            faultFound = false;
            // When an input fault occurs, the power supply cannot be on.
            // However, the check for the case where the power supply should be
            // on will stop when there is a fault found.
            // Clear the powerOnFault when the inputFault is cleared to reset
            // the powerOnFault de-glitching.
            powerOnFault = 0;

            log<level::INFO>("INPUT_FAULT_WARN cleared",
                             entry("POWERSUPPLY=%s", inventoryPath.c_str()));

            resolveError(inventoryPath,
                         std::string(PowerSupplyInputFault::errName));

            if (powerOn)
            {
                // The power supply will not be immediately powered on after
                // the input power is restored.
                powerOn = false;
                // Start up the timer that will set the state to indicate we
                // are ready for the powered on fault checks.
                powerOnTimer.restartOnce(powerOnInterval);
            }
        }
    }

    if (!faultFound && (inputFault >= FAULT_COUNT))
    {
        // If the power is on, report the fault in an error log entry.
        if (powerOn)
        {
            util::NamesValues nv;
            nv.add("STATUS_WORD", statusWord);
            captureCmd(nv, STATUS_INPUT, Type::Debug);

            using metadata =
                org::open_power::Witherspoon::Fault::PowerSupplyInputFault;

            report<PowerSupplyInputFault>(
                metadata::RAW_STATUS(nv.get().c_str()),
                metadata::CALLOUT_INVENTORY_PATH(inventoryPath.c_str()));

            faultFound = true;
        }
    }
}

void PowerSupply::checkPGOrUnitOffFault(const uint16_t statusWord)
{
    using namespace witherspoon::pmbus;

    if (powerOnFault < FAULT_COUNT)
    {
        // Check PG# and UNIT_IS_OFF
        if ((statusWord & status_word::POWER_GOOD_NEGATED) ||
            (statusWord & status_word::UNIT_IS_OFF))
        {
            log<level::INFO>("PGOOD or UNIT_IS_OFF bit bad",
                             entry("STATUS_WORD=0x%04X", statusWord));
            powerOnFault++;
        }
        else
        {
            if (powerOnFault > 0)
            {
                log<level::INFO>("PGOOD and UNIT_IS_OFF bits good");
                powerOnFault = 0;
            }
        }

        if (!faultFound && (powerOnFault >= FAULT_COUNT))
        {
            faultFound = true;

            util::NamesValues nv;
            nv.add("STATUS_WORD", statusWord);
            captureCmd(nv, STATUS_INPUT, Type::Debug);
            auto status0Vout = pmbusIntf.insertPageNum(STATUS_VOUT, 0);
            captureCmd(nv, status0Vout, Type::Debug);
            captureCmd(nv, STATUS_IOUT, Type::Debug);
            captureCmd(nv, STATUS_MFR, Type::Debug);

            using metadata =
                org::open_power::Witherspoon::Fault::PowerSupplyShouldBeOn;

            // A power supply is OFF (or pgood low) but should be on.
            report<PowerSupplyShouldBeOn>(
                metadata::RAW_STATUS(nv.get().c_str()),
                metadata::CALLOUT_INVENTORY_PATH(inventoryPath.c_str()));
        }
    }
}

void PowerSupply::checkCurrentOutOverCurrentFault(const uint16_t statusWord)
{
    using namespace witherspoon::pmbus;

    if (outputOCFault < FAULT_COUNT)
    {
        // Check for an output overcurrent fault.
        if ((statusWord & status_word::IOUT_OC_FAULT))
        {
            outputOCFault++;
        }
        else
        {
            if (outputOCFault > 0)
            {
                outputOCFault = 0;
            }
        }

        if (!faultFound && (outputOCFault >= FAULT_COUNT))
        {
            util::NamesValues nv;
            nv.add("STATUS_WORD", statusWord);
            captureCmd(nv, STATUS_INPUT, Type::Debug);
            auto status0Vout = pmbusIntf.insertPageNum(STATUS_VOUT, 0);
            captureCmd(nv, status0Vout, Type::Debug);
            captureCmd(nv, STATUS_IOUT, Type::Debug);
            captureCmd(nv, STATUS_MFR, Type::Debug);

            using metadata = org::open_power::Witherspoon::Fault::
                PowerSupplyOutputOvercurrent;

            report<PowerSupplyOutputOvercurrent>(
                metadata::RAW_STATUS(nv.get().c_str()),
                metadata::CALLOUT_INVENTORY_PATH(inventoryPath.c_str()));

            faultFound = true;
        }
    }
}

void PowerSupply::checkOutputOvervoltageFault(const uint16_t statusWord)
{
    using namespace witherspoon::pmbus;

    if (outputOVFault < FAULT_COUNT)
    {
        // Check for an output overvoltage fault.
        if (statusWord & status_word::VOUT_OV_FAULT)
        {
            outputOVFault++;
        }
        else
        {
            if (outputOVFault > 0)
            {
                outputOVFault = 0;
            }
        }

        if (!faultFound && (outputOVFault >= FAULT_COUNT))
        {
            util::NamesValues nv;
            nv.add("STATUS_WORD", statusWord);
            captureCmd(nv, STATUS_INPUT, Type::Debug);
            auto status0Vout = pmbusIntf.insertPageNum(STATUS_VOUT, 0);
            captureCmd(nv, status0Vout, Type::Debug);
            captureCmd(nv, STATUS_IOUT, Type::Debug);
            captureCmd(nv, STATUS_MFR, Type::Debug);

            using metadata = org::open_power::Witherspoon::Fault::
                PowerSupplyOutputOvervoltage;

            report<PowerSupplyOutputOvervoltage>(
                metadata::RAW_STATUS(nv.get().c_str()),
                metadata::CALLOUT_INVENTORY_PATH(inventoryPath.c_str()));

            faultFound = true;
        }
    }
}

void PowerSupply::checkFanFault(const uint16_t statusWord)
{
    using namespace witherspoon::pmbus;

    if (fanFault < FAULT_COUNT)
    {
        // Check for a fan fault or warning condition
        if (statusWord & status_word::FAN_FAULT)
        {
            fanFault++;
        }
        else
        {
            if (fanFault > 0)
            {
                fanFault = 0;
            }
        }

        if (!faultFound && (fanFault >= FAULT_COUNT))
        {
            util::NamesValues nv;
            nv.add("STATUS_WORD", statusWord);
            captureCmd(nv, STATUS_MFR, Type::Debug);
            captureCmd(nv, STATUS_TEMPERATURE, Type::Debug);
            captureCmd(nv, STATUS_FANS_1_2, Type::Debug);

            using metadata =
                org::open_power::Witherspoon::Fault::PowerSupplyFanFault;

            report<PowerSupplyFanFault>(
                metadata::RAW_STATUS(nv.get().c_str()),
                metadata::CALLOUT_INVENTORY_PATH(inventoryPath.c_str()));

            faultFound = true;
        }
    }
}

void PowerSupply::checkTemperatureFault(const uint16_t statusWord)
{
    using namespace witherspoon::pmbus;

    // Due to how the PMBus core device driver sends a clear faults command
    // the bit in STATUS_WORD will likely be cleared when we attempt to examine
    // it for a Thermal Fault or Warning. So, check the STATUS_WORD and the
    // STATUS_TEMPERATURE bits. If either indicates a fault, proceed with
    // logging the over-temperature condition.
    std::uint8_t statusTemperature = 0;
    statusTemperature = pmbusIntf.read(STATUS_TEMPERATURE, Type::Debug);
    if (temperatureFault < FAULT_COUNT)
    {
        if ((statusWord & status_word::TEMPERATURE_FAULT_WARN) ||
            (statusTemperature & status_temperature::OT_FAULT))
        {
            temperatureFault++;
        }
        else
        {
            if (temperatureFault > 0)
            {
                temperatureFault = 0;
            }
        }

        if (!faultFound && (temperatureFault >= FAULT_COUNT))
        {
            // The power supply has had an over-temperature condition.
            // This may not result in a shutdown if experienced for a short
            // duration.
            // This should not occur under normal conditions.
            // The power supply may be faulty, or the paired supply may be
            // putting out less current.
            // Capture command responses with potentially relevant information,
            // and call out the power supply reporting the condition.
            util::NamesValues nv;
            nv.add("STATUS_WORD", statusWord);
            captureCmd(nv, STATUS_MFR, Type::Debug);
            captureCmd(nv, STATUS_IOUT, Type::Debug);
            nv.add("STATUS_TEMPERATURE", statusTemperature);
            captureCmd(nv, STATUS_FANS_1_2, Type::Debug);

            using metadata = org::open_power::Witherspoon::Fault::
                PowerSupplyTemperatureFault;

            report<PowerSupplyTemperatureFault>(
                metadata::RAW_STATUS(nv.get().c_str()),
                metadata::CALLOUT_INVENTORY_PATH(inventoryPath.c_str()));

            faultFound = true;
        }
    }
}

void PowerSupply::clearFaults()
{
    readFail = 0;
    readFailLogged = false;
    inputFault = 0;
    powerOnFault = 0;
    outputOCFault = 0;
    outputOVFault = 0;
    fanFault = 0;
    temperatureFault = 0;
    faultFound = false;

    return;
}

void PowerSupply::resolveError(const std::string& callout,
                               const std::string& message)
{
    using EndpointList = std::vector<std::string>;

    try
    {
        auto path = callout + "/fault";
        // Get the service name from the mapper for the fault callout
        auto service = util::getService(path, ASSOCIATION_IFACE, bus);

        // Use getProperty utility function to get log entries (endpoints)
        EndpointList logEntries;
        util::getProperty(ASSOCIATION_IFACE, ENDPOINTS_PROP, path, service, bus,
                          logEntries);

        // It is possible that all such entries for this callout have since
        // been deleted.
        if (logEntries.empty())
        {
            return;
        }

        auto logEntryService =
            util::getService(logEntries[0], LOGGING_IFACE, bus);
        if (logEntryService.empty())
        {
            return;
        }

        // go through each log entry that matches this callout path
        std::string logMessage;
        for (const auto& logEntry : logEntries)
        {
            // Check to see if this logEntry has a message that matches.
            util::getProperty(LOGGING_IFACE, MESSAGE_PROP, logEntry,
                              logEntryService, bus, logMessage);

            if (message == logMessage)
            {
                // Log entry matches call out and message, set Resolved to true
                bool resolved = true;
                util::setProperty(LOGGING_IFACE, RESOLVED_PROP, logEntry,
                                  logEntryService, bus, resolved);
            }
        }
    }
    catch (std::exception& e)
    {
        log<level::INFO>("Failed to resolve error",
                         entry("CALLOUT=%s", callout.c_str()),
                         entry("ERROR=%s", message.c_str()));
    }
}

void PowerSupply::updateInventory()
{
    using namespace witherspoon::pmbus;
    using namespace sdbusplus::message;

    // If any of these accesses fail, the fields will just be
    // blank in the inventory.  Leave logging ReadFailure errors
    // to analyze() as it runs continuously and will most
    // likely hit and threshold them first anyway.  The
    // readString() function will do the tracing of the failing
    // path so this code doesn't need to.
    std::string pn;
    std::string sn;
    std::string ccin;
    std::string version;

    if (present)
    {
        try
        {
            sn = pmbusIntf.readString(SERIAL_NUMBER, Type::HwmonDeviceDebug);
        }
        catch (ReadFailure& e)
        {
        }

        try
        {
            pn = pmbusIntf.readString(PART_NUMBER, Type::HwmonDeviceDebug);
        }
        catch (ReadFailure& e)
        {
        }

        try
        {
            ccin = pmbusIntf.readString(CCIN, Type::HwmonDeviceDebug);
        }
        catch (ReadFailure& e)
        {
        }

        try
        {
            version = pmbusIntf.readString(FW_VERSION, Type::HwmonDeviceDebug);
        }
        catch (ReadFailure& e)
        {
        }
    }

    // Build the object map and send it to the inventory
    using Properties = std::map<std::string, variant<std::string>>;
    using Interfaces = std::map<std::string, Properties>;
    using Object = std::map<object_path, Interfaces>;
    Properties assetProps;
    Properties versionProps;
    Interfaces interfaces;
    Object object;

    assetProps.emplace(SN_PROP, sn);
    assetProps.emplace(PN_PROP, pn);
    assetProps.emplace(MODEL_PROP, ccin);
    interfaces.emplace(ASSET_IFACE, std::move(assetProps));

    versionProps.emplace(VERSION_PROP, version);
    interfaces.emplace(VERSION_IFACE, std::move(versionProps));

    // For Notify(), just send the relative path of the inventory
    // object so remove the INVENTORY_OBJ_PATH prefix
    auto path = inventoryPath.substr(strlen(INVENTORY_OBJ_PATH));

    object.emplace(path, std::move(interfaces));

    try
    {
        auto service =
            util::getService(INVENTORY_OBJ_PATH, INVENTORY_MGR_IFACE, bus);

        if (service.empty())
        {
            log<level::ERR>("Unable to get inventory manager service");
            return;
        }

        auto method = bus.new_method_call(service.c_str(), INVENTORY_OBJ_PATH,
                                          INVENTORY_MGR_IFACE, "Notify");

        method.append(std::move(object));

        auto reply = bus.call(method);

        // TODO: openbmc/openbmc#2756
        // Calling Notify() with an enumerated property crashes inventory
        // manager, so let it default to Unknown and now set it to the
        // right value.
        auto purpose =
            version::convertForMessage(version::Version::VersionPurpose::Other);

        util::setProperty(VERSION_IFACE, VERSION_PURPOSE_PROP, inventoryPath,
                          service, bus, purpose);
    }
    catch (std::exception& e)
    {
        log<level::ERR>(e.what(), entry("PATH=%s", inventoryPath.c_str()));
    }
}

void PowerSupply::syncHistory()
{
    using namespace witherspoon::gpio;

    if (syncGPIODevPath.empty())
    {
        // Sync not implemented
        return;
    }

    GPIO gpio{syncGPIODevPath, static_cast<gpioNum_t>(syncGPIONumber),
              Direction::output};

    try
    {
        gpio.set(Value::low);

        std::this_thread::sleep_for(std::chrono::milliseconds{5});

        gpio.set(Value::high);

        recordManager->clear();
    }
    catch (std::exception& e)
    {
        // Do nothing.  There would already be a journal entry.
    }
}

void PowerSupply::enableHistory(const std::string& objectPath,
                                size_t numRecords,
                                const std::string& syncGPIOPath,
                                size_t syncGPIONum)
{
    historyObjectPath = objectPath;
    syncGPIODevPath = syncGPIOPath;
    syncGPIONumber = syncGPIONum;

    recordManager = std::make_unique<history::RecordManager>(numRecords);

    auto avgPath = historyObjectPath + '/' + history::Average::name;
    auto maxPath = historyObjectPath + '/' + history::Maximum::name;

    average = std::make_unique<history::Average>(bus, avgPath);

    maximum = std::make_unique<history::Maximum>(bus, maxPath);
}

void PowerSupply::updateHistory()
{
    if (!recordManager)
    {
        // Not enabled
        return;
    }

    // Read just the most recent average/max record
    auto data =
        pmbusIntf.readBinary(INPUT_HISTORY, pmbus::Type::HwmonDeviceDebug,
                             history::RecordManager::RAW_RECORD_SIZE);

    // Update D-Bus only if something changed (a new record ID, or cleared out)
    auto changed = recordManager->add(data);
    if (changed)
    {
        average->values(std::move(recordManager->getAverageRecords()));
        maximum->values(std::move(recordManager->getMaximumRecords()));
    }
}

} // namespace psu
} // namespace power
} // namespace witherspoon
