/*
// Copyright (c) 2020 Intel 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 "cpuinfo.hpp"

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>

#include <boost/asio/io_service.hpp>
#include <boost/asio/steady_timer.hpp>

#include <optional>
#include <sstream>
#include <string>

extern "C"
{
#include <i2c/smbus.h>
#include <linux/i2c-dev.h>
}

#include <peci.h>

#include <phosphor-logging/log.hpp>
#include <sdbusplus/asio/object_server.hpp>

namespace phosphor
{
namespace cpu_info
{

static constexpr const char* cpuPath =
    "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu";
static constexpr const char* cpuInterfaceName =
    "xyz.openbmc_project.Inventory.Decorator.Asset";
static constexpr const char* cpuProcessName =
    "xyz.openbmc_project.Smbios.MDR_V2";

struct ProcessorInfo
{
    uint64_t ppin;
    std::string sspec;
};

using CPUMap =
    boost::container::flat_map<size_t,
                               std::pair<int, std::shared_ptr<CPUInfo>>>;

static CPUMap cpuMap = {};

static std::unique_ptr<sdbusplus::bus::match_t> cpuUpdatedMatch = nullptr;

static std::optional<std::string> readSSpec(uint8_t bus, uint8_t slaveAddr,
                                            uint8_t regAddr, size_t count)
{
    unsigned long funcs = 0;
    std::string devPath = "/dev/i2c-" + std::to_string(bus);

    int fd = ::open(devPath.c_str(), O_RDWR);
    if (fd < 0)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Error in open!",
            phosphor::logging::entry("PATH=%s", devPath.c_str()),
            phosphor::logging::entry("SLAVEADDR=0x%x", slaveAddr));
        return std::nullopt;
    }

    if (::ioctl(fd, I2C_FUNCS, &funcs) < 0)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Error in I2C_FUNCS!",
            phosphor::logging::entry("PATH=%s", devPath.c_str()),
            phosphor::logging::entry("SLAVEADDR=0x%x", slaveAddr));
        ::close(fd);
        return std::nullopt;
    }

    if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA))
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "i2c bus does not support read!",
            phosphor::logging::entry("PATH=%s", devPath.c_str()),
            phosphor::logging::entry("SLAVEADDR=0x%x", slaveAddr));
        ::close(fd);
        return std::nullopt;
    }

    if (::ioctl(fd, I2C_SLAVE_FORCE, slaveAddr) < 0)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Error in I2C_SLAVE_FORCE!",
            phosphor::logging::entry("PATH=%s", devPath.c_str()),
            phosphor::logging::entry("SLAVEADDR=0x%x", slaveAddr));
        ::close(fd);
        return std::nullopt;
    }

    int value = 0;
    std::string sspec;
    sspec.reserve(count);

    for (size_t i = 0; i < count; i++)
    {
        value = ::i2c_smbus_read_byte_data(fd, regAddr++);
        if (value < 0)
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Error in i2c read!",
                phosphor::logging::entry("PATH=%s", devPath.c_str()),
                phosphor::logging::entry("SLAVEADDR=0x%x", slaveAddr));
            ::close(fd);
            return std::nullopt;
        }
        if (!std::isprint(static_cast<unsigned char>(value)))
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Non printable value in sspec, ignored.");
            continue;
        }
        sspec.push_back(static_cast<unsigned char>(value));
    }
    ::close(fd);
    return sspec;
}

// PECI Client Address Map
static void getPECIAddrMap(CPUMap& cpuMap)
{
    int idx = 0;
    for (size_t i = MIN_CLIENT_ADDR; i <= MAX_CLIENT_ADDR; i++)
    {
        if (peci_Ping(i) == PECI_CC_SUCCESS)
        {
            cpuMap.emplace(std::make_pair(i, std::make_pair(idx, nullptr)));
            idx++;
        }
    }
}

static std::shared_ptr<CPUInfo>
    createCPUInfo(std::shared_ptr<sdbusplus::asio::connection>& conn,
                  const int& cpu)
{
    std::string path = cpuPath + std::to_string(cpu);
    std::shared_ptr<CPUInfo> cpuInfo = std::make_shared<CPUInfo>(
        static_cast<sdbusplus::bus::bus&>(*conn), path);
    return cpuInfo;
}

static void setAssetProperty(
    std::shared_ptr<sdbusplus::asio::connection>& conn, const int& cpu,
    const std::vector<std::pair<std::string, std::string>>& propValues)
{

    const std::string objectPath = cpuPath + std::to_string(cpu);
    for (const auto& prop : propValues)
    {
        conn->async_method_call(
            [](const boost::system::error_code ec) {
                // Use "Set" method to set the property value.
                if (ec)
                {
                    phosphor::logging::log<phosphor::logging::level::ERR>(
                        "Cannot get CPU property!");
                    return;
                }
            },
            cpuProcessName, objectPath.c_str(),
            "org.freedesktop.DBus.Properties", "Set", cpuInterfaceName,
            prop.first.c_str(), std::variant<std::string>{prop.second});
    }
}

static void createCpuUpdatedMatch(
    std::shared_ptr<sdbusplus::asio::connection>& conn, const int& cpu,
    const std::vector<std::pair<std::string, std::string>>& propValues)
{
    if (cpuUpdatedMatch)
    {
        return;
    }

    const std::string objectPath = cpuPath + std::to_string(cpu);

    cpuUpdatedMatch = std::make_unique<sdbusplus::bus::match::match>(
        static_cast<sdbusplus::bus::bus&>(*conn),
        sdbusplus::bus::match::rules::interfacesAdded() +
            sdbusplus::bus::match::rules::argNpath(0, objectPath.c_str()),
        [&conn, cpu, propValues](sdbusplus::message::message& msg) {
            sdbusplus::message::object_path objectName;
            boost::container::flat_map<
                std::string,
                boost::container::flat_map<std::string,
                                           std::variant<std::string, uint64_t>>>
                msgData;

            msg.read(objectName, msgData);

            // Check for xyz.openbmc_project.Inventory.Item.Cpu
            // interface match
            auto intfFound = msgData.find(cpuInterfaceName);
            if (msgData.end() != intfFound)
            {
                setAssetProperty(conn, cpu, propValues);
            }
        });
}

// constants for reading QDF string from PIROM
// Currently, they are the same for platforms with icx
// \todo: move into configuration file to be more robust
static constexpr uint8_t i2cBus = 13;
static constexpr uint8_t slaveAddr0 = 0x50;
static constexpr uint8_t regAddr = 0xf;
static constexpr uint8_t sspecSize = 4;

static void getProcessorInfo(std::shared_ptr<sdbusplus::asio::connection>& conn,
                             sdbusplus::asio::object_server& objServer,
                             CPUMap& cpuMap)
{

    for (auto& cpu : cpuMap)
    {
        uint8_t cc = 0;
        CPUModel model{};
        uint8_t stepping = 0;

        /// \todo in a follwup patch
        // CPUInfo will be updated as the centrol place for CPU information
        // std::shared_ptr<CPUInfo> cpuInfo =
        //    createCPUInfo(conn, cpu.second.first);
        // cpu.second.second = cpuInfo;

        if (peci_GetCPUID(cpu.first, &model, &stepping, &cc) != PECI_CC_SUCCESS)
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Cannot get CPUID!",
                phosphor::logging::entry("PECIADDR=0x%x", cpu.first));
            continue;
        }

        switch (model)
        {
            case icx:
            {
                // get processor ID
                static constexpr uint8_t u8Size = 4; // default to a DWORD
                static constexpr uint8_t u8PPINPkgIndex = 19;
                static constexpr uint16_t u16PPINPkgParamHigh = 2;
                static constexpr uint16_t u16PPINPkgParamLow = 1;
                uint64_t cpuPPIN = 0;
                uint32_t u32PkgValue = 0;

                int ret = peci_RdPkgConfig(cpu.first, u8PPINPkgIndex,
                                           u16PPINPkgParamLow, u8Size,
                                           (uint8_t*)&u32PkgValue, &cc);
                if (0 != ret)
                {
                    phosphor::logging::log<phosphor::logging::level::ERR>(
                        "peci read package config failed at address",
                        phosphor::logging::entry("PECIADDR=0x%x", cpu.first),
                        phosphor::logging::entry("CC=0x%x", cc));
                    u32PkgValue = 0;
                }

                cpuPPIN = u32PkgValue;
                ret = peci_RdPkgConfig(cpu.first, u8PPINPkgIndex,
                                       u16PPINPkgParamHigh, u8Size,
                                       (uint8_t*)&u32PkgValue, &cc);
                if (0 != ret)
                {
                    phosphor::logging::log<phosphor::logging::level::ERR>(
                        "peci read package config failed at address",
                        phosphor::logging::entry("PECIADDR=0x%x", cpu.first),
                        phosphor::logging::entry("CC=0x%x", cc));
                    cpuPPIN = 0;
                    u32PkgValue = 0;
                }

                cpuPPIN |= static_cast<uint64_t>(u32PkgValue) << 32;

                std::vector<std::pair<std::string, std::string>> values;

                // set SerialNumber if cpuPPIN is valid
                if (0 != cpuPPIN)
                {
                    std::stringstream stream;
                    stream << std::hex << cpuPPIN;
                    std::string serialNumber(stream.str());
                    // cpuInfo->serialNumber(serialNumber);
                    values.emplace_back(
                        std::make_pair("SerialNumber", serialNumber));
                }

                // assuming the slaveAddress will be incrementing like peci
                // client address
                std::optional<std::string> sspec = readSSpec(
                    i2cBus, static_cast<uint8_t>(slaveAddr0 + cpu.second.first),
                    regAddr, sspecSize);
                // cpuInfo->model(sspec.value_or(""));
                values.emplace_back(
                    std::make_pair("Model", sspec.value_or("")));

                /// \todo in followup patch
                // CPUInfo is created by this service
                // update the below logic, which is needed because smbios
                // service creates the cpu object
                createCpuUpdatedMatch(conn, cpu.second.first, values);
                setAssetProperty(conn, cpu.second.first, values);
                break;
            }
            default:
                phosphor::logging::log<phosphor::logging::level::INFO>(
                    "in-compatible cpu for cpu asset info");
                break;
        }
    }
}

static bool isPECIAvailable(void)
{
    for (size_t i = MIN_CLIENT_ADDR; i <= MAX_CLIENT_ADDR; i++)
    {
        if (peci_Ping(i) == PECI_CC_SUCCESS)
        {
            return true;
        }
    }
    return false;
}

static void
    peciAvailableCheck(boost::asio::steady_timer& peciWaitTimer,
                       boost::asio::io_service& io,
                       std::shared_ptr<sdbusplus::asio::connection>& conn,
                       sdbusplus::asio::object_server& objServer)
{
    bool peciAvailable = isPECIAvailable();
    if (peciAvailable)
    {
        // get the PECI client address list
        getPECIAddrMap(cpuMap);
        getProcessorInfo(conn, objServer, cpuMap);
    }
    if (!peciAvailable || !cpuMap.size())
    {
        peciWaitTimer.expires_after(
            std::chrono::seconds(6 * peciCheckInterval));
        peciWaitTimer.async_wait([&peciWaitTimer, &io, &conn, &objServer](
                                     const boost::system::error_code& ec) {
            if (ec)
            {
                // operation_aborted is expected if timer is canceled
                // before completion.
                if (ec != boost::asio::error::operation_aborted)
                {
                    phosphor::logging::log<phosphor::logging::level::ERR>(
                        "PECI Available Check async_wait failed",
                        phosphor::logging::entry("EC=0x%x", ec.value()));
                }
                return;
            }
            peciAvailableCheck(peciWaitTimer, io, conn, objServer);
        });
    }
}

} // namespace cpu_info
} // namespace phosphor

int main(int argc, char* argv[])
{
    // setup connection to dbus
    boost::asio::io_service io;
    std::shared_ptr<sdbusplus::asio::connection> conn =
        std::make_shared<sdbusplus::asio::connection>(io);

    // CPUInfo Object
    conn->request_name(phosphor::cpu_info::cpuInfoObject);
    sdbusplus::asio::object_server server =
        sdbusplus::asio::object_server(conn);
    sdbusplus::bus::bus& bus = static_cast<sdbusplus::bus::bus&>(*conn);
    sdbusplus::server::manager::manager objManager(
        bus, "/xyz/openbmc_project/inventory");

    // Start the PECI check loop
    boost::asio::steady_timer peciWaitTimer(
        io, std::chrono::seconds(phosphor::cpu_info::peciCheckInterval));
    peciWaitTimer.async_wait([&peciWaitTimer, &io, &conn,
                              &server](const boost::system::error_code& ec) {
        if (ec)
        {
            // operation_aborted is expected if timer is canceled
            // before completion.
            if (ec != boost::asio::error::operation_aborted)
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "PECI Available Check async_wait failed ",
                    phosphor::logging::entry("EC=0x%x", ec.value()));
            }
            return;
        }
        phosphor::cpu_info::peciAvailableCheck(peciWaitTimer, io, conn, server);
    });

    io.run();

    return 0;
}
