#include "sessions_manager.hpp"

#include "main.hpp"
#include "session.hpp"

#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <user_channel/channel_layer.hpp>

#include <algorithm>
#include <cstdlib>
#include <iomanip>
#include <memory>

namespace session
{

static std::array<uint8_t, session::maxNetworkInstanceSupported>
    ipmiNetworkChannelNumList = {0};

void Manager::setNetworkInstance(void)
{
    uint8_t index = 0, ch = 1;
    // Constructing net-ipmid instances list based on channel info
    // valid channel start from 1 to 15  and assuming max 4 LAN channel
    // supported

    while (ch < ipmi::maxIpmiChannels &&
           index < session::maxNetworkInstanceSupported)
    {
        ipmi::ChannelInfo chInfo;
        ipmi::getChannelInfo(ch, chInfo);
        if (static_cast<ipmi::EChannelMediumType>(chInfo.mediumType) ==
            ipmi::EChannelMediumType::lan8032)
        {
            if (getInterfaceIndex() == ch)
            {
                ipmiNetworkInstance = index;
            }

            ipmiNetworkChannelNumList[index] = ch;
            index++;
        }
        ch++;
    }
}

uint8_t Manager::getNetworkInstance(void)
{
    return ipmiNetworkInstance;
}

void Manager::managerInit(const std::string& channel)
{
    /*
     * Session ID is 0000_0000h for messages that are sent outside the session.
     * The session setup commands are sent on this session, so when the session
     * manager comes up, is creates the Session ID  0000_0000h. It is active
     * through the lifetime of the Session Manager.
     */

    objManager = std::make_unique<sdbusplus::server::manager_t>(
        *getSdBus(), session::sessionManagerRootPath);

    auto objPath =
        std::string(session::sessionManagerRootPath) + "/" + channel + "/0";

    chName = channel;
    setNetworkInstance();
    sessionsMap.emplace(
        0, std::make_shared<Session>(*getSdBus(), objPath.c_str(), 0, 0, 0));

    // set up the timer for clearing out stale sessions
    scheduleSessionCleaner(std::chrono::microseconds(3 * 1000 * 1000));
}

std::shared_ptr<Session>
    Manager::startSession(SessionID remoteConsoleSessID, Privilege priv,
                          cipher::rakp_auth::Algorithms authAlgo,
                          cipher::integrity::Algorithms intAlgo,
                          cipher::crypt::Algorithms cryptAlgo)
{
    std::shared_ptr<Session> session = nullptr;
    SessionID bmcSessionID = 0;
    cleanStaleEntries();
    // set up the timer for monitoring this session
    scheduleSessionCleaner(std::chrono::microseconds(1 * 1000 * 1000));

    uint8_t sessionHandle = 0;

    auto activeSessions = sessionsMap.size() - session::maxSessionlessCount;

    if (activeSessions < maxSessionHandles)
    {
        do
        {
            bmcSessionID = (crypto::prng::rand());
            bmcSessionID &= session::multiIntfaceSessionIDMask;
            // In sessionID , BIT 31 BIT30 are used for netipmid instance
            bmcSessionID |= static_cast<uint32_t>(ipmiNetworkInstance) << 30;
            /*
             * Every IPMI Session has two ID's attached to it Remote Console
             * Session ID and BMC Session ID. The remote console ID is passed
             * along with the Open Session request command. The BMC session ID
             * is the key for the session map and is generated using std::rand.
             * There is a rare chance for collision of BMC session ID, so the
             * following check validates that. In the case of collision the
             * created session is reset and a new session is created for
             * validating collision.
             */
            auto iterator = sessionsMap.find(bmcSessionID);
            if (iterator != sessionsMap.end())
            {
                // Detected BMC Session ID collisions
                continue;
            }
            else
            {
                break;
            }
        } while (1);

        sessionHandle = storeSessionHandle(bmcSessionID);

        if (!sessionHandle)
        {
            throw std::runtime_error(
                "Invalid sessionHandle - No sessionID slot ");
        }
        sessionHandle &= session::multiIntfaceSessionHandleMask;
        // In sessionID , BIT 31 BIT30 are used for netipmid instance
        sessionHandle |= static_cast<uint8_t>(ipmiNetworkInstance) << 6;
        std::stringstream sstream;
        sstream << std::hex << bmcSessionID;
        std::stringstream shstream;
        shstream << std::hex << (int)sessionHandle;
        auto objPath = std::string(session::sessionManagerRootPath) + "/" +
                       chName + "/" + sstream.str() + "_" + shstream.str();
        session = std::make_shared<Session>(*getSdBus(), objPath.c_str(),
                                            remoteConsoleSessID, bmcSessionID,
                                            static_cast<uint8_t>(priv));

        // Set the Authentication Algorithm
        switch (authAlgo)
        {
            case cipher::rakp_auth::Algorithms::RAKP_HMAC_SHA1:
            {
                session->setAuthAlgo(
                    std::make_unique<cipher::rakp_auth::AlgoSHA1>(intAlgo,
                                                                  cryptAlgo));
                break;
            }
            case cipher::rakp_auth::Algorithms::RAKP_HMAC_SHA256:
            {
                session->setAuthAlgo(
                    std::make_unique<cipher::rakp_auth::AlgoSHA256>(intAlgo,
                                                                    cryptAlgo));
                break;
            }
            default:
            {
                throw std::runtime_error("Invalid Authentication Algorithm");
            }
        }

        sessionsMap.emplace(bmcSessionID, session);
        session->sessionHandle(sessionHandle);

        return session;
    }

    lg2::info("No free RMCP+ sessions left");

    throw std::runtime_error("No free sessions left");
}

bool Manager::stopSession(SessionID bmcSessionID)
{
    auto iter = sessionsMap.find(bmcSessionID);
    if (iter != sessionsMap.end())
    {
        iter->second->state(
            static_cast<uint8_t>(session::State::tearDownInProgress));
        return true;
    }
    else
    {
        return false;
    }
}

std::shared_ptr<Session> Manager::getSession(SessionID sessionID,
                                             RetrieveOption option)
{
    switch (option)
    {
        case RetrieveOption::BMC_SESSION_ID:
        {
            auto iter = sessionsMap.find(sessionID);
            if (iter != sessionsMap.end())
            {
                return iter->second;
            }
            break;
        }
        case RetrieveOption::RC_SESSION_ID:
        {
            auto iter = std::find_if(
                sessionsMap.begin(), sessionsMap.end(),
                [sessionID](
                    const std::pair<const uint32_t, std::shared_ptr<Session>>&
                        in) -> bool {
                    return sessionID == in.second->getRCSessionID();
                });

            if (iter != sessionsMap.end())
            {
                return iter->second;
            }
            break;
        }
        default:
            throw std::runtime_error("Invalid retrieval option");
    }

    throw std::runtime_error("Session ID not found");
}

void Manager::cleanStaleEntries()
{
    // with overflow = min(1, max - active sessions)
    // active idle time in seconds = 60 / overflow^3
    constexpr int baseIdleMicros = 60 * 1000 * 1000;
    // no +1 for the zero session here because this is just active sessions
    int sessionDivisor =
        getActiveSessionCount() - session::maxSessionCountPerChannel;
    sessionDivisor = std::max(0, sessionDivisor) + 1;
    sessionDivisor = sessionDivisor * sessionDivisor * sessionDivisor;
    int activeMicros = baseIdleMicros / sessionDivisor;

    // with overflow = min(1, max - total sessions)
    // setup idle time in seconds = max(3, 60 / overflow^3)

    // +1 for the zero session here because size() counts that too
    int setupDivisor =
        sessionsMap.size() - (session::maxSessionCountPerChannel + 1);
    setupDivisor = std::max(0, setupDivisor) + 1;
    setupDivisor = setupDivisor * setupDivisor * setupDivisor;
    constexpr int maxSetupMicros = 3 * 1000 * 1000;
    int setupMicros = std::min(maxSetupMicros, baseIdleMicros / setupDivisor);

    std::chrono::microseconds activeGrace(activeMicros);
    std::chrono::microseconds setupGrace(setupMicros);

    for (auto iter = sessionsMap.begin(); iter != sessionsMap.end();)
    {
        auto session = iter->second;
        // special handling for sessionZero
        if (session->getBMCSessionID() == session::sessionZero)
        {
            iter++;
            continue;
        }
        if (!(session->isSessionActive(activeGrace, setupGrace)))
        {
            lg2::info(
                "Removing idle IPMI LAN session, id: {ID}, handler: {HANDLE}",
                "ID", session->getBMCSessionID(), "HANDLE",
                getSessionHandle(session->getBMCSessionID()));
            sessionHandleMap[getSessionHandle(session->getBMCSessionID())] = 0;
            iter = sessionsMap.erase(iter);
        }
        else
        {
            iter++;
        }
    }
    if (sessionsMap.size() > 1)
    {
        constexpr int maxCleanupDelay = 1 * 1000 * 1000;
        std::chrono::microseconds cleanupDelay(
            std::min(setupMicros, maxCleanupDelay));
        scheduleSessionCleaner(cleanupDelay);
    }
}

uint8_t Manager::storeSessionHandle(SessionID bmcSessionID)
{
    // Handler index 0 is  reserved for invalid session.
    // index starts with 1, for direct usage. Index 0 reserved
    for (size_t i = 1; i < session::maxSessionHandles; i++)
    {
        if (sessionHandleMap[i] == 0)
        {
            sessionHandleMap[i] = bmcSessionID;
            return i;
        }
    }
    return 0;
}

uint32_t Manager::getSessionIDbyHandle(uint8_t sessionHandle) const
{
    if (sessionHandle < session::maxSessionHandles)
    {
        return sessionHandleMap[sessionHandle];
    }
    return 0;
}

uint8_t Manager::getSessionHandle(SessionID bmcSessionID) const
{
    // Handler index 0 is reserved for invalid session.
    // index starts with 1, for direct usage. Index 0 reserved
    for (size_t i = 1; i < session::maxSessionHandles; i++)
    {
        if (sessionHandleMap[i] == bmcSessionID)
        {
            return (i);
        }
    }
    return 0;
}
uint8_t Manager::getActiveSessionCount() const
{
    return (std::count_if(
        sessionsMap.begin(), sessionsMap.end(),
        [](const std::pair<const uint32_t, std::shared_ptr<Session>>& in)
            -> bool {
            return in.second->state() ==
                   static_cast<uint8_t>(session::State::active);
        }));
}

void Manager::scheduleSessionCleaner(const std::chrono::microseconds& when)
{
    std::chrono::duration expTime = timer.expires_from_now();
    if (expTime > std::chrono::microseconds(0) && expTime < when)
    {
        // if timer has not already expired AND requested timeout is greater
        // than current timeout then ignore this new requested timeout
        return;
    }
    timer.expires_from_now(when);
    timer.async_wait([this](const boost::system::error_code& ec) {
        if (!ec)
        {
            cleanStaleEntries();
        }
    });
}

} // namespace session
