#include "sessions_manager.hpp"

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

#include <algorithm>
#include <cstdlib>
#include <iomanip>
#include <memory>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <user_channel/channel_layer.hpp>

using namespace phosphor::logging;

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::manager>(
        *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;
    }

    log<level::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)))
        {
            log<level::INFO>(
                "Removing idle IPMI LAN session",
                entry("SESSION_ID=%x", session->getBMCSessionID()),
                entry("HANDLE=%x",
                      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
