#include "nvme_manager.hpp"

#include "smbus.hpp"

#include <filesystem>
#include <map>
#include <nlohmann/json.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/message.hpp>
#include <sstream>
#include <string>
#include <xyz/openbmc_project/Led/Physical/server.hpp>

#include "i2c.h"
#define MONITOR_INTERVAL_SECONDS 1
#define NVME_SSD_SLAVE_ADDRESS 0x6a
#define NVME_SSD_VPD_SLAVE_ADDRESS 0x53
#define GPIO_BASE_PATH "/sys/class/gpio/gpio"
#define IS_PRESENT "0"
#define POWERGD "1"
#define NOWARNING_STRING "ff"

static constexpr auto configFile = "/etc/nvme/nvme_config.json";
static constexpr auto delay = std::chrono::milliseconds{100};
using Json = nlohmann::json;

static constexpr const uint8_t COMMAND_CODE_0 = 0;
static constexpr const uint8_t COMMAND_CODE_8 = 8;
static constexpr const uint8_t CODE_0_LENGTH = 8;
static constexpr const uint8_t CODE_8_LENGTH = 23;

static constexpr int CapacityFaultMask = 1;
static constexpr int temperatureFaultMask = 1 << 1;
static constexpr int DegradesFaultMask = 1 << 2;
static constexpr int MediaFaultMask = 1 << 3;
static constexpr int BackupDeviceFaultMask = 1 << 4;
static constexpr int NOWARNING = 255;

static constexpr int SERIALNUMBER_START_INDEX = 3;
static constexpr int SERIALNUMBER_END_INDEX = 23;
static constexpr int MODELNUMBER_START_INDEX = 46;
static constexpr int MODELNUMBER_END_INDEX = 85;

static constexpr const int TEMPERATURE_SENSOR_FAILURE = 0x81;

static std::map<std::string, std::string> map_vendor = {
    {"80 86", "Intel"}, {"1e f", "Kioxia"}, {"14 4d", "Samsung"}};

namespace fs = std::filesystem;

namespace phosphor
{
namespace nvme
{

using namespace std;
using namespace phosphor::logging;

void Nvme::setNvmeInventoryProperties(
    NVMeConfig& config, bool present,
    const phosphor::nvme::Nvme::NVMeData& nvmeData,
    const std::string& inventoryPath)
{
    static std::unordered_map<int, std::string> preSerial;
    static std::unordered_map<int, std::string> preSmartWarning;
    static std::unordered_map<int, std::string> preStatusFlags;

    if (preSerial[config.busID].compare(nvmeData.serialNumber) != 0)
    {
        util::SDBusPlus::setProperty(bus, INVENTORY_BUSNAME, inventoryPath,
                                     ITEM_IFACE, "Present", present);
        util::SDBusPlus::setProperty(bus, INVENTORY_BUSNAME, inventoryPath,
                                     ASSET_IFACE, "Manufacturer",
                                     nvmeData.vendor);
        util::SDBusPlus::setProperty(bus, INVENTORY_BUSNAME, inventoryPath,
                                     ASSET_IFACE, "SerialNumber",
                                     nvmeData.serialNumber);
        util::SDBusPlus::setProperty(bus, INVENTORY_BUSNAME, inventoryPath,
                                     ASSET_IFACE, "Model",
                                     nvmeData.modelNumber);
        util::SDBusPlus::setProperty(bus, INVENTORY_BUSNAME, inventoryPath,
                                     NVME_STATUS_IFACE, "DriveLifeUsed",
                                     nvmeData.driveLifeUsed);
        preSerial[config.busID] = nvmeData.serialNumber;
    }

    if (preStatusFlags[config.busID].compare(nvmeData.statusFlags) != 0)
    {
        util::SDBusPlus::setProperty(bus, INVENTORY_BUSNAME, inventoryPath,
                                     NVME_STATUS_IFACE, "StatusFlags",
                                     nvmeData.statusFlags);
        preStatusFlags[config.busID] = nvmeData.statusFlags;
    }

    if (preSmartWarning[config.busID].compare(nvmeData.smartWarnings) != 0)
    {
        util::SDBusPlus::setProperty(bus, INVENTORY_BUSNAME, inventoryPath,
                                     NVME_STATUS_IFACE, "SmartWarnings",
                                     nvmeData.smartWarnings);
        auto smartWarning = (!nvmeData.smartWarnings.empty())
                                ? std::stoi(nvmeData.smartWarnings, 0, 16)
                                : NOWARNING;

        util::SDBusPlus::setProperty(bus, INVENTORY_BUSNAME, inventoryPath,
                                     NVME_STATUS_IFACE, "CapacityFault",
                                     !(smartWarning & CapacityFaultMask));

        util::SDBusPlus::setProperty(bus, INVENTORY_BUSNAME, inventoryPath,
                                     NVME_STATUS_IFACE, "TemperatureFault",
                                     !(smartWarning & temperatureFaultMask));

        util::SDBusPlus::setProperty(bus, INVENTORY_BUSNAME, inventoryPath,
                                     NVME_STATUS_IFACE, "DegradesFault",
                                     !(smartWarning & DegradesFaultMask));

        util::SDBusPlus::setProperty(bus, INVENTORY_BUSNAME, inventoryPath,
                                     NVME_STATUS_IFACE, "MediaFault",
                                     !(smartWarning & MediaFaultMask));

        util::SDBusPlus::setProperty(bus, INVENTORY_BUSNAME, inventoryPath,
                                     NVME_STATUS_IFACE, "BackupDeviceFault",
                                     !(smartWarning & BackupDeviceFaultMask));
        preSmartWarning[config.busID] = nvmeData.smartWarnings;
    }
}

void Nvme::setFaultLED(const std::string& locateLedGroupPath,
                       const std::string& faultLedGroupPath, bool request)
{
    if (locateLedGroupPath.empty() || faultLedGroupPath.empty())
    {
        return;
    }

    // Before toggle LED, check whether is Identify or not.
    if (!getLEDGroupState(locateLedGroupPath))
    {
        if (getLEDGroupState(faultLedGroupPath) != request)
        {
            util::SDBusPlus::setProperty(bus, LED_GROUP_BUSNAME,
                                         faultLedGroupPath, LED_GROUP_IFACE,
                                         "Asserted", request);
        }
    }
}

void Nvme::setLocateLED(const std::string& locateLedGroupPath,
                        const std::string& locateLedBusName,
                        const std::string& locateLedPath, bool isPresent)
{
    if (locateLedGroupPath.empty() || locateLedBusName.empty() ||
        locateLedPath.empty())
    {
        return;
    }

    namespace server = sdbusplus::xyz::openbmc_project::Led::server;

    if (!getLEDGroupState(locateLedGroupPath))
    {
        if (isPresent)
            util::SDBusPlus::setProperty(
                bus, locateLedBusName, locateLedPath, LED_CONTROLLER_IFACE,
                "State",
                server::convertForMessage(server::Physical::Action::On));
        else
            util::SDBusPlus::setProperty(
                bus, locateLedBusName, locateLedPath, LED_CONTROLLER_IFACE,
                "State",
                server::convertForMessage(server::Physical::Action::Off));
    }
}

bool Nvme::getLEDGroupState(const std::string& ledPath)
{
    auto asserted = util::SDBusPlus::getProperty<bool>(
        bus, LED_GROUP_BUSNAME, ledPath, LED_GROUP_IFACE, "Asserted");

    return asserted;
}

void Nvme::setLEDsStatus(const phosphor::nvme::Nvme::NVMeConfig& config,
                         bool success,
                         const phosphor::nvme::Nvme::NVMeData& nvmeData)
{

    if (success)
    {
        if (!nvmeData.smartWarnings.empty())
        {
            auto request =
                (strcmp(nvmeData.smartWarnings.c_str(), NOWARNING_STRING) == 0)
                    ? false
                    : true;

            setFaultLED(config.locateLedGroupPath, config.faultLedGroupPath,
                        request);
            setLocateLED(config.locateLedGroupPath,
                         config.locateLedControllerBusName,
                         config.locateLedControllerPath, !request);
        }
        isError[config.index] = false;
    }
    else
    {
        if (isError[config.index] != true)
        {
            // Drive is present but can not get data, turn on fault LED.
            log<level::ERR>("Drive status is good but can not get data.",
                            entry("OBJ_PATH=%s", config.index.c_str()));
            isError[config.index] = true;
        }

        setFaultLED(config.locateLedGroupPath, config.faultLedGroupPath, true);
        setLocateLED(config.locateLedGroupPath,
                     config.locateLedControllerBusName,
                     config.locateLedControllerPath, false);
    }
}

std::string intToHex(int input)
{
    std::stringstream tmp;
    tmp << std::hex << input;

    return tmp.str();
}

/** @brief Get NVMe info over smbus  */
bool Nvme::getNVMeInfobyBusID(int busID,
                              phosphor::nvme::Nvme::NVMeData& nvmeData)
{
    nvmeData.present = true;
    nvmeData.vendor = "";
    nvmeData.serialNumber = "";
    nvmeData.modelNumber = "";
    nvmeData.smartWarnings = "";
    nvmeData.statusFlags = "";
    nvmeData.driveLifeUsed = "";
    nvmeData.sensorValue = static_cast<int8_t>(TEMPERATURE_SENSOR_FAILURE);
    nvmeData.wcTemp = 0;

    phosphor::smbus::Smbus smbus;

    unsigned char rsp_data_command_0[I2C_DATA_MAX] = {0};
    unsigned char rsp_data_command_8[I2C_DATA_MAX] = {0};

    uint8_t tx_data = COMMAND_CODE_0;

    auto init = smbus.smbusInit(busID);

    if (init == -1)
    {
        if (isErrorSmbus[busID] != true)
        {
            log<level::ERR>("smbusInit fail!");
            isErrorSmbus[busID] = true;
        }

        nvmeData.present = false;

        return nvmeData.present;
    }

    auto res_int = smbus.SendSmbusRWCmdRAW(busID, NVME_SSD_SLAVE_ADDRESS,
                                           &tx_data, sizeof(tx_data),
                                           rsp_data_command_0, CODE_0_LENGTH);

    if (res_int < 0)
    {
        if (isErrorSmbus[busID] != true)
        {
            log<level::ERR>("Send command code 0 fail!");
            isErrorSmbus[busID] = true;
        }

        smbus.smbusClose(busID);
        nvmeData.present = false;
        return nvmeData.present;
    }

    nvmeData.statusFlags = intToHex(rsp_data_command_0[1]);
    nvmeData.smartWarnings = intToHex(rsp_data_command_0[2]);
    nvmeData.driveLifeUsed = intToHex(rsp_data_command_0[4]);
    nvmeData.sensorValue = static_cast<int8_t>(rsp_data_command_0[3]);
    nvmeData.wcTemp = static_cast<int8_t>(rsp_data_command_0[5]);

    tx_data = COMMAND_CODE_8;

    res_int = smbus.SendSmbusRWCmdRAW(busID, NVME_SSD_SLAVE_ADDRESS, &tx_data,
                                      sizeof(tx_data), rsp_data_command_8,
                                      CODE_8_LENGTH);

    if (res_int < 0)
    {
        if (isErrorSmbus[busID] != true)
        {
            log<level::ERR>("Send command code 8 fail!");
            isErrorSmbus[busID] = true;
        }

        smbus.smbusClose(busID);
        nvmeData.present = false;
        return nvmeData.present;
    }

    nvmeData.vendor =
        intToHex(rsp_data_command_8[1]) + " " + intToHex(rsp_data_command_8[2]);

    for (auto iter = map_vendor.begin(); iter != map_vendor.end(); iter++)
    {
        if (iter->first == nvmeData.vendor)
        {
            nvmeData.vendor = iter->second;
            break;
        }
    }

    for (int offset = SERIALNUMBER_START_INDEX; offset < SERIALNUMBER_END_INDEX;
         offset++)
    {
        // Only accept digits/letters/punctuation characters.
        if (rsp_data_command_8[offset] >= '!' &&
            rsp_data_command_8[offset] <= '~')
            nvmeData.serialNumber +=
                static_cast<char>(rsp_data_command_8[offset]);
    }

    if (nvmeData.vendor == "Samsung")
    {
        unsigned char rsp_data_vpd[I2C_DATA_MAX] = {0};
        const int rx_len = (MODELNUMBER_END_INDEX - MODELNUMBER_START_INDEX);
        tx_data = MODELNUMBER_START_INDEX;

        auto res_int =
            smbus.SendSmbusRWCmdRAW(busID, NVME_SSD_VPD_SLAVE_ADDRESS, &tx_data,
                                    sizeof(tx_data), rsp_data_vpd, rx_len);

        if (res_int < 0)
        {
            if (isErrorSmbus[busID] != true)
            {
                log<level::ERR>("Send command read VPD fail!");
                isErrorSmbus[busID] = true;
            }

            smbus.smbusClose(busID);
            nvmeData.present = false;
            return nvmeData.present;
        }

        for (int i = 0; i < rx_len; i++)
        {
            // Only accept digits/letters/punctuation characters.
            if ((rsp_data_vpd[i] >= '!' && rsp_data_vpd[i] <= '~'))
                nvmeData.modelNumber += static_cast<char>(rsp_data_vpd[i]);
        }

        if (nvmeData.modelNumber.substr(0, nvmeData.vendor.size()) == "SAMSUNG")
            nvmeData.modelNumber.erase(0, nvmeData.vendor.size());
    }

    smbus.smbusClose(busID);

    isErrorSmbus[busID] = false;

    return nvmeData.present;
}

void Nvme::run()
{
    init();

    std::function<void()> callback(std::bind(&Nvme::read, this));
    try
    {
        u_int64_t interval = MONITOR_INTERVAL_SECONDS * 1000000;
        _timer.restart(std::chrono::microseconds(interval));
    }
    catch (const std::exception& e)
    {
        log<level::ERR>("Error in polling loop. "), entry("ERROR=%s", e.what());
    }
}

/** @brief Parsing NVMe config JSON file  */
Json parseSensorConfig()
{
    std::ifstream jsonFile(configFile);
    if (!jsonFile.is_open())
    {
        log<level::ERR>("NVMe config JSON file not found");
    }

    auto data = Json::parse(jsonFile, nullptr, false);
    if (data.is_discarded())
    {
        log<level::ERR>("NVMe config readings JSON parser failure");
    }

    return data;
}

/** @brief Obtain the initial configuration value of NVMe  */
std::vector<phosphor::nvme::Nvme::NVMeConfig> Nvme::getNvmeConfig()
{

    phosphor::nvme::Nvme::NVMeConfig nvmeConfig;
    std::vector<phosphor::nvme::Nvme::NVMeConfig> nvmeConfigs;
    int8_t criticalHigh = 0;
    int8_t criticalLow = 0;
    int8_t maxValue = 0;
    int8_t minValue = 0;
    int8_t warningHigh = 0;
    int8_t warningLow = 0;

    try
    {
        auto data = parseSensorConfig();
        static const std::vector<Json> empty{};
        std::vector<Json> readings = data.value("config", empty);
        std::vector<Json> thresholds = data.value("threshold", empty);
        if (!thresholds.empty())
        {
            for (const auto& instance : thresholds)
            {
                criticalHigh = instance.value("criticalHigh", 0);
                criticalLow = instance.value("criticalLow", 0);
                maxValue = instance.value("maxValue", 0);
                minValue = instance.value("minValue", 0);
                warningHigh = instance.value("warningHigh", 0);
                warningLow = instance.value("warningLow", 0);
            }
        }
        else
        {
            log<level::ERR>(
                "Invalid NVMe config file, thresholds dosen't exist");
        }

        if (!readings.empty())
        {
            for (const auto& instance : readings)
            {
                uint8_t index = instance.value("NVMeDriveIndex", 0);
                uint8_t busID = instance.value("NVMeDriveBusID", 0);
                std::string faultLedGroupPath =
                    instance.value("NVMeDriveFaultLEDGroupPath", "");
                std::string locateLedGroupPath =
                    instance.value("NVMeDriveLocateLEDGroupPath", "");
                uint16_t presentPin = instance.value("NVMeDrivePresentPin", 0);
                uint16_t pwrGoodPin = instance.value("NVMeDrivePwrGoodPin", 0);
                std::string locateLedControllerBusName =
                    instance.value("NVMeDriveLocateLEDControllerBusName", "");
                std::string locateLedControllerPath =
                    instance.value("NVMeDriveLocateLEDControllerPath", "");

                nvmeConfig.index = std::to_string(index);
                nvmeConfig.busID = busID;
                nvmeConfig.faultLedGroupPath = faultLedGroupPath;
                nvmeConfig.presentPin = presentPin;
                nvmeConfig.pwrGoodPin = pwrGoodPin;
                nvmeConfig.locateLedControllerBusName =
                    locateLedControllerBusName;
                nvmeConfig.locateLedControllerPath = locateLedControllerPath;
                nvmeConfig.locateLedGroupPath = locateLedGroupPath;
                nvmeConfig.criticalHigh = criticalHigh;
                nvmeConfig.criticalLow = criticalLow;
                nvmeConfig.warningHigh = warningHigh;
                nvmeConfig.warningLow = warningLow;
                nvmeConfig.maxValue = maxValue;
                nvmeConfig.minValue = minValue;
                nvmeConfigs.push_back(nvmeConfig);
            }
        }
        else
        {
            log<level::ERR>("Invalid NVMe config file, config dosen't exist");
        }
    }
    catch (const Json::exception& e)
    {
        log<level::ERR>("Json Exception caught."), entry("MSG=%s", e.what());
    }

    return nvmeConfigs;
}

std::string Nvme::getGPIOValueOfNvme(const std::string& fullPath)
{
    std::string val;
    std::ifstream ifs;
    auto retries = 3;

    while (retries != 0)
    {
        try
        {
            if (!ifs.is_open())
                ifs.open(fullPath);
            ifs.clear();
            ifs.seekg(0);
            ifs >> val;
        }
        catch (const std::exception& e)
        {
            --retries;
            std::this_thread::sleep_for(delay);
            log<level::ERR>("Can not open gpio path.",
                            entry("MSG=%s", e.what()));
            continue;
        }
        break;
    }

    ifs.close();
    return val;
}

void Nvme::createNVMeInventory()
{
    using Properties = std::map<std::string, std::variant<std::string, bool>>;
    using Interfaces = std::map<std::string, Properties>;

    std::string inventoryPath;
    std::map<sdbusplus::message::object_path, Interfaces> obj;

    for (const auto& config : configs)
    {
        inventoryPath = "/system/chassis/motherboard/nvme" + config.index;

        obj = {{
            inventoryPath,
            {{ITEM_IFACE, {}}, {NVME_STATUS_IFACE, {}}, {ASSET_IFACE, {}}},
        }};
        util::SDBusPlus::CallMethod(bus, INVENTORY_BUSNAME, INVENTORY_NAMESPACE,
                                    INVENTORY_MANAGER_IFACE, "Notify", obj);
    }
}

void Nvme::init()
{
    createNVMeInventory();
}

void Nvme::readNvmeData(NVMeConfig& config)
{
    std::string inventoryPath = NVME_INVENTORY_PATH + config.index;
    NVMeData nvmeData;

    // get NVMe information through i2c by busID.
    auto success = getNVMeInfobyBusID(config.busID, nvmeData);
    auto iter = nvmes.find(config.index);

    // can not find. create dbus
    if (iter == nvmes.end())
    {
        log<level::INFO>("SSD plug.", entry("INDEX=%s", config.index.c_str()));

        std::string objPath = NVME_OBJ_PATH + config.index;
        auto nvmeSSD =
            std::make_shared<phosphor::nvme::NvmeSSD>(bus, objPath.c_str());
        nvmes.emplace(config.index, nvmeSSD);

        setNvmeInventoryProperties(config, true, nvmeData, inventoryPath);
        nvmeSSD->setSensorValueToDbus(nvmeData.sensorValue);
        if (nvmeData.wcTemp != 0)
        {
            config.criticalHigh = nvmeData.wcTemp;
            config.warningHigh = nvmeData.wcTemp;
        }
        nvmeSSD->setSensorMaxMin(config.maxValue, config.minValue);
        nvmeSSD->setSensorThreshold(config.criticalHigh, config.criticalLow,
                                    config.warningHigh, config.warningLow);

        nvmeSSD->checkSensorThreshold();
        setLEDsStatus(config, success, nvmeData);
    }
    else
    {
        setNvmeInventoryProperties(config, true, nvmeData, inventoryPath);
        iter->second->setSensorValueToDbus(nvmeData.sensorValue);
        if (nvmeData.wcTemp != 0)
        {
            config.criticalHigh = nvmeData.wcTemp;
            config.warningHigh = nvmeData.wcTemp;

            iter->second->setSensorThreshold(
                config.criticalHigh, config.criticalLow, config.warningHigh,
                config.warningLow);
        }
        iter->second->checkSensorThreshold();
        setLEDsStatus(config, success, nvmeData);
    }
}

/** @brief Monitor NVMe drives every one second  */
void Nvme::read()
{
    std::string devPresentPath;
    std::string devPwrGoodPath;
    std::string inventoryPath;

    for (auto config : configs)
    {
        NVMeData nvmeData;

        inventoryPath = NVME_INVENTORY_PATH + config.index;

        if (config.presentPin)
        {
            devPresentPath =
                GPIO_BASE_PATH + std::to_string(config.presentPin) + "/value";

            if (getGPIOValueOfNvme(devPresentPath) != IS_PRESENT)
            {
                // Drive not present, remove nvme d-bus path ,
                // clean all properties in inventory
                // and turn off fault and locate LED

                setFaultLED(config.locateLedGroupPath, config.faultLedGroupPath,
                            false);
                setLocateLED(config.locateLedGroupPath,
                             config.locateLedControllerBusName,
                             config.locateLedControllerPath, false);

                nvmeData = NVMeData();
                setNvmeInventoryProperties(config, false, nvmeData,
                                           inventoryPath);
                nvmes.erase(config.index);
                continue;
            }
            else if (config.pwrGoodPin)
            {
                devPwrGoodPath = GPIO_BASE_PATH +
                                 std::to_string(config.pwrGoodPin) + "/value";

                if (getGPIOValueOfNvme(devPwrGoodPath) != POWERGD)
                {
                    // IFDET should be used to provide the final say
                    // in SSD's presence - IFDET showing SSD is present
                    // but the power is off (if the drive is plugged in)
                    // is a valid state.

                    setFaultLED(config.locateLedGroupPath,
                                config.faultLedGroupPath, true);
                    setLocateLED(config.locateLedGroupPath,
                                 config.locateLedControllerBusName,
                                 config.locateLedControllerPath, false);

                    nvmeData = NVMeData();
                    setNvmeInventoryProperties(config, true, nvmeData,
                                               inventoryPath);

                    if (isErrorPower[config.index] != true)
                    {
                        log<level::ERR>(
                            "Present pin is true but power good pin is false.",
                            entry("INDEX=%s", config.index.c_str()));
                        log<level::ERR>(
                            "Erase SSD from map and d-bus.",
                            entry("INDEX=%s", config.index.c_str()));

                        isErrorPower[config.index] = true;
                    }

                    // Keep reading to report the invalid temperature
                    // (To make thermal loop know that the sensor reading
                    //  is invalid).
                    readNvmeData(config);
                    continue;
                }
            }
        }
        // Drive status is good, update value or create d-bus and update
        // value.
        readNvmeData(config);

        isErrorPower[config.index] = false;
    }
}
} // namespace nvme
} // namespace phosphor
