/*
// Copyright (c) 2018 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 "ChassisIntrusionSensor.hpp"
#include "Utils.hpp"

#include <boost/asio/io_context.hpp>
#include <boost/container/flat_map.hpp>
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/bus/match.hpp>
#include <sdbusplus/exception.hpp>
#include <sdbusplus/server.hpp>
#include <sdbusplus/timer.hpp>

#include <array>
#include <charconv>
#include <chrono>
#include <ctime>
#include <fstream>
#include <functional>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>

static constexpr bool debug = false;

static constexpr const char* sensorType = "ChassisIntrusionSensor";
static constexpr const char* nicType = "NIC";
static constexpr auto nicTypes{std::to_array<const char*>({nicType})};

static void createSensorsFromConfig(
    boost::asio::io_context& io, sdbusplus::asio::object_server& objServer,
    const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
    std::shared_ptr<ChassisIntrusionSensor>& pSensor)
{
    // find matched configuration according to sensor type
    ManagedObjectType sensorConfigurations;
    bool useCache = false;

    if (!getSensorConfiguration(sensorType, dbusConnection,
                                sensorConfigurations, useCache))
    {
        std::cerr << "error communicating to entity manager\n";
        return;
    }

    const SensorData* sensorData = nullptr;
    const std::pair<std::string, SensorBaseConfigMap>* baseConfiguration =
        nullptr;

    // Get bus and addr of matched configuration
    for (const auto& [path, cfgData] : sensorConfigurations)
    {
        baseConfiguration = nullptr;
        sensorData = &cfgData;

        // match sensor type
        auto sensorBase = sensorData->find(configInterfaceName(sensorType));
        if (sensorBase == sensorData->end())
        {
            std::cerr << "error finding base configuration \n";
            continue;
        }

        baseConfiguration = &(*sensorBase);

        // judge class, "Gpio" or "I2C"
        auto findClass = baseConfiguration->second.find("Class");
        if (findClass != baseConfiguration->second.end() &&
            std::get<std::string>(findClass->second) == "Gpio")
        {
            auto findGpioPolarity =
                baseConfiguration->second.find("GpioPolarity");

            if (findGpioPolarity == baseConfiguration->second.end())
            {
                std::cerr << "error finding gpio polarity in configuration \n";
                continue;
            }

            try
            {
                bool gpioInverted =
                    (std::get<std::string>(findGpioPolarity->second) == "Low");
                pSensor = std::make_shared<ChassisIntrusionGpioSensor>(
                    io, objServer, gpioInverted);
                pSensor->start();
                if (debug)
                {
                    std::cout
                        << "find chassis intrusion sensor polarity inverted "
                           "flag is "
                        << gpioInverted << "\n";
                }
                return;
            }
            catch (const std::bad_variant_access& e)
            {
                std::cerr << "invalid value for gpio info in config. \n";
                continue;
            }
            catch (const std::exception& e)
            {
                std::cerr << e.what() << std::endl;
                continue;
            }
        }
        else
        {
            auto findBus = baseConfiguration->second.find("Bus");
            auto findAddress = baseConfiguration->second.find("Address");
            if (findBus == baseConfiguration->second.end() ||
                findAddress == baseConfiguration->second.end())
            {
                std::cerr << "error finding bus or address in configuration \n";
                continue;
            }
            try
            {
                int busId = std::get<uint64_t>(findBus->second);
                int slaveAddr = std::get<uint64_t>(findAddress->second);
                pSensor = std::make_shared<ChassisIntrusionPchSensor>(
                    io, objServer, busId, slaveAddr);
                pSensor->start();
                if (debug)
                {
                    std::cout << "find matched bus " << busId
                              << ", matched slave addr " << slaveAddr << "\n";
                }
                return;
            }
            catch (const std::bad_variant_access& e)
            {
                std::cerr << "invalid value for bus or address in config. \n";
                continue;
            }
            catch (const std::exception& e)
            {
                std::cerr << e.what() << std::endl;
                continue;
            }
        }
    }

    std::cerr << " Can't find matched I2C, GPIO configuration\n";

    // Make sure nothing runs when there's failure in configuration for the
    // sensor after rescan
    if (pSensor)
    {
        std::cerr << " Reset the occupied sensor pointer\n";
        pSensor = nullptr;
    }
}

static constexpr bool debugLanLeash = false;
boost::container::flat_map<int, bool> lanStatusMap;
boost::container::flat_map<int, std::string> lanInfoMap;
boost::container::flat_map<std::string, int> pathSuffixMap;

static void getNicNameInfo(
    const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
{
    auto getter = std::make_shared<GetSensorConfiguration>(
        dbusConnection,
        [](const ManagedObjectType& sensorConfigurations) {
        // Get NIC name and save to map
        lanInfoMap.clear();
        for (const auto& [path, cfgData] : sensorConfigurations)
        {
            const std::pair<std::string, SensorBaseConfigMap>*
                baseConfiguration = nullptr;

            // find base configuration
            auto sensorBase = cfgData.find(configInterfaceName(nicType));
            if (sensorBase == cfgData.end())
            {
                continue;
            }
            baseConfiguration = &(*sensorBase);

            auto findEthIndex = baseConfiguration->second.find("EthIndex");
            auto findName = baseConfiguration->second.find("Name");

            if (findEthIndex != baseConfiguration->second.end() &&
                findName != baseConfiguration->second.end())
            {
                const auto* pEthIndex =
                    std::get_if<uint64_t>(&findEthIndex->second);
                const auto* pName = std::get_if<std::string>(&findName->second);
                if (pEthIndex != nullptr && pName != nullptr)
                {
                    lanInfoMap[*pEthIndex] = *pName;
                    if (debugLanLeash)
                    {
                        std::cout << "find name of eth" << *pEthIndex << " is "
                                  << *pName << "\n";
                    }
                }
            }
        }

        if (lanInfoMap.empty())
        {
            std::cerr << "can't find matched NIC name. \n";
        }
        });

    getter->getConfiguration(
        std::vector<std::string>{nicTypes.begin(), nicTypes.end()});
}

static void processLanStatusChange(sdbusplus::message_t& message)
{
    const std::string& pathName = message.get_path();
    std::string interfaceName;
    SensorBaseConfigMap properties;
    message.read(interfaceName, properties);

    auto findStateProperty = properties.find("OperationalState");
    if (findStateProperty == properties.end())
    {
        return;
    }
    std::string* pState =
        std::get_if<std::string>(&(findStateProperty->second));
    if (pState == nullptr)
    {
        std::cerr << "invalid OperationalState \n";
        return;
    }

    bool newLanConnected = (*pState == "routable" || *pState == "carrier" ||
                            *pState == "degraded");

    // get ethNum from path. /org/freedesktop/network1/link/_32 for eth0
    size_t pos = pathName.find("/_");
    if (pos == std::string::npos || pathName.length() <= pos + 2)
    {
        std::cerr << "unexpected path name " << pathName << "\n";
        return;
    }
    std::string suffixStr = pathName.substr(pos + 2);

    auto findEthNum = pathSuffixMap.find(suffixStr);
    if (findEthNum == pathSuffixMap.end())
    {
        std::cerr << "unexpected eth for suffixStr " << suffixStr << "\n";
        return;
    }
    int ethNum = findEthNum->second;

    // get lan status from map
    auto findLanStatus = lanStatusMap.find(ethNum);
    if (findLanStatus == lanStatusMap.end())
    {
        std::cerr << "unexpected eth " << ethNum << " in lanStatusMap \n";
        return;
    }
    bool oldLanConnected = findLanStatus->second;

    // get lan info from map
    std::string lanInfo;
    if (!lanInfoMap.empty())
    {
        auto findLanInfo = lanInfoMap.find(ethNum);
        if (findLanInfo == lanInfoMap.end())
        {
            std::cerr << "unexpected eth " << ethNum << " in lanInfoMap \n";
        }
        else
        {
            lanInfo = "(" + findLanInfo->second + ")";
        }
    }

    if (debugLanLeash)
    {
        std::cout << "ethNum = " << ethNum << ", state = " << *pState
                  << ", oldLanConnected = "
                  << (oldLanConnected ? "true" : "false")
                  << ", newLanConnected = "
                  << (newLanConnected ? "true" : "false") << "\n";
    }

    if (oldLanConnected != newLanConnected)
    {
        std::string strEthNum = "eth" + std::to_string(ethNum) + lanInfo;
        const auto* strState = newLanConnected ? "connected" : "lost";
        const auto* strMsgId = newLanConnected ? "OpenBMC.0.1.LanRegained"
                                               : "OpenBMC.0.1.LanLost";

        lg2::info("{ETHDEV} LAN leash {STATE}", "ETHDEV", strEthNum, "STATE",
                  strState, "REDFISH_MESSAGE_ID", strMsgId,
                  "REDFISH_MESSAGE_ARGS", strEthNum);

        lanStatusMap[ethNum] = newLanConnected;
    }
}

/** @brief Initialize the lan status.
 *
 * @return true on success and false on failure
 */
static bool initializeLanStatus(
    const std::shared_ptr<sdbusplus::asio::connection>& conn)
{
    // init lan port name from configuration
    getNicNameInfo(conn);

    // get eth info from sysfs
    std::vector<fs::path> files;
    if (!findFiles(fs::path("/sys/class/net/"), R"(eth\d+/ifindex)", files))
    {
        std::cerr << "No eth in system\n";
        return false;
    }

    // iterate through all found eth files, and save ifindex
    for (const fs::path& fileName : files)
    {
        if (debugLanLeash)
        {
            std::cout << "Reading " << fileName << "\n";
        }
        std::ifstream sysFile(fileName);
        if (!sysFile.good())
        {
            std::cerr << "Failure reading " << fileName << "\n";
            continue;
        }
        std::string line;
        getline(sysFile, line);
        const uint8_t ifindex = std::stoi(line);
        // pathSuffix is ASCII of ifindex
        const std::string& pathSuffix = std::to_string(ifindex + 30);

        // extract ethNum
        const std::string& fileStr = fileName.string();
        const int pos = fileStr.find("eth");
        const std::string& ethNumStr = fileStr.substr(pos + 3);
        int ethNum = 0;
        std::from_chars_result r = std::from_chars(
            ethNumStr.data(), ethNumStr.data() + ethNumStr.size(), ethNum);
        if (r.ec != std::errc())
        {
            std::cerr << "invalid ethNum string: " << ethNumStr << "\n";
            continue;
        }

        // save pathSuffix
        pathSuffixMap[pathSuffix] = ethNum;
        if (debugLanLeash)
        {
            std::cout << "ethNum = " << std::to_string(ethNum)
                      << ", ifindex = " << line
                      << ", pathSuffix = " << pathSuffix << "\n";
        }

        // init lan connected status from networkd
        conn->async_method_call(
            [ethNum](boost::system::error_code ec,
                     const std::variant<std::string>& property) {
            lanStatusMap[ethNum] = false;
            if (ec)
            {
                std::cerr << "Error reading init status of eth" << ethNum
                          << "\n";
                return;
            }
            const std::string* pState = std::get_if<std::string>(&property);
            if (pState == nullptr)
            {
                std::cerr << "Unable to read lan status value\n";
                return;
            }
            bool isLanConnected = (*pState == "routable" ||
                                   *pState == "carrier" ||
                                   *pState == "degraded");
            if (debugLanLeash)
            {
                std::cout << "ethNum = " << std::to_string(ethNum)
                          << ", init LAN status = "
                          << (isLanConnected ? "true" : "false") << "\n";
            }
            lanStatusMap[ethNum] = isLanConnected;
            },
            "org.freedesktop.network1",
            "/org/freedesktop/network1/link/_" + pathSuffix,
            "org.freedesktop.DBus.Properties", "Get",
            "org.freedesktop.network1.Link", "OperationalState");
    }
    return true;
}

int main()
{
    std::shared_ptr<ChassisIntrusionSensor> intrusionSensor;

    // setup connection to dbus
    boost::asio::io_context io;
    auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);

    // setup object server, define interface
    systemBus->request_name("xyz.openbmc_project.IntrusionSensor");

    sdbusplus::asio::object_server objServer(systemBus, true);

    objServer.add_manager("/xyz/openbmc_project/Chassis");

    createSensorsFromConfig(io, objServer, systemBus, intrusionSensor);

    // callback to handle configuration change
    std::function<void(sdbusplus::message_t&)> eventHandler =
        [&](sdbusplus::message_t& message) {
        if (message.is_method_error())
        {
            std::cerr << "callback method error\n";
            return;
        }

        std::cout << "rescan due to configuration change \n";
        createSensorsFromConfig(io, objServer, systemBus, intrusionSensor);
    };

    std::vector<std::unique_ptr<sdbusplus::bus::match_t>> matches =
        setupPropertiesChangedMatches(
            *systemBus, std::to_array<const char*>({sensorType}), eventHandler);

    if (initializeLanStatus(systemBus))
    {
        // add match to monitor lan status change
        sdbusplus::bus::match_t lanStatusMatch(
            static_cast<sdbusplus::bus_t&>(*systemBus),
            "type='signal', member='PropertiesChanged',"
            "arg0namespace='org.freedesktop.network1.Link'",
            [](sdbusplus::message_t& msg) { processLanStatusChange(msg); });

        // add match to monitor entity manager signal about nic name config
        // change
        sdbusplus::bus::match_t lanConfigMatch(
            static_cast<sdbusplus::bus_t&>(*systemBus),
            "type='signal', member='PropertiesChanged',path_namespace='" +
                std::string(inventoryPath) + "',arg0namespace='" +
                configInterfaceName(nicType) + "'",
            [&systemBus](sdbusplus::message_t& msg) {
            if (msg.is_method_error())
            {
                std::cerr << "callback method error\n";
                return;
            }
            getNicNameInfo(systemBus);
            });
    }

    io.run();

    return 0;
}
