#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.expiry() - boost::asio::steady_timer::clock_type::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_after(when);
    timer.async_wait([this](const boost::system::error_code& ec) {
        if (!ec)
        {
            cleanStaleEntries();
        }
    });
}

} // namespace session
