#include "sessions_manager.hpp"

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

#include "session.hpp"

namespace session
{

Manager::Manager()
{
    /*
     * 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.
     */
    sessionsMap.emplace(0, std::make_shared<Session>());
    // Seeding the pseudo-random generator
    std::srand(std::time(0));
}

std::weak_ptr<Session> Manager::startSession(SessionID remoteConsoleSessID,
        Privilege priv, cipher::rakp_auth::Algorithms authAlgo)
{
    std::shared_ptr<Session> session = nullptr;
    SessionID sessionID = 0;
    cleanStaleEntries();
    auto activeSessions = sessionsMap.size() - MAX_SESSIONLESS_COUNT;

    if (activeSessions < MAX_SESSION_COUNT)
    {
        do
        {
            session = std::make_shared<Session>(remoteConsoleSessID, priv);

            /*
             * 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 reseted and a new session is created for
             * validating collision.
             */
            auto iterator = sessionsMap.find(session->getBMCSessionID());
            if (iterator != sessionsMap.end())
            {
               //Detected BMC Session ID collisions
                session.reset();
                continue;
            }
            else
            {
                break;
            }
        }
        while (1);

        // Set the Authentication Algorithm to RAKP_HMAC_SHA1
        switch (authAlgo)
        {
            case cipher::rakp_auth::Algorithms::RAKP_HMAC_SHA1:
            {
                session->setAuthAlgo(
                        std::make_unique<cipher::rakp_auth::AlgoSHA1>());
                break;
            }
            default:
            {
                throw std::runtime_error("Invalid Authentication Algorithm");
            }
        }
        sessionID = session->getBMCSessionID();
        sessionsMap.emplace(sessionID, std::move(session));
    }
    else
    {
        std::cerr << "E> No free sessions left: Active: " << activeSessions <<
                  " Allowed: " <<
                  MAX_SESSION_COUNT << "\n";

        for (const auto& iterator : sessionsMap)
        {
            std::cerr << "E> Active Session: 0x" << std::hex
                      << std::setfill('0') << std::setw(8)
                      << (iterator.second)->getBMCSessionID() << "\n";
        }
        throw std::runtime_error("No free sessions left");
    }

    return getSession(sessionID);
}

void Manager::stopSession(SessionID bmcSessionID)
{
    // If the session is valid and not session zero
    if(bmcSessionID != SESSION_ZERO)
    {
        auto iter = sessionsMap.find(bmcSessionID);
        if (iter != sessionsMap.end())
        {
            iter->second->state = State::TEAR_DOWN_IN_PROGRESS;
        }
    }
}

std::weak_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;
            }
        }
        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;
            }
        }
        default:
            throw std::runtime_error("Invalid retrieval option");
    }

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

void Manager::cleanStaleEntries()
{
    for(auto iter = sessionsMap.begin(); iter != sessionsMap.end();)
    {
        auto session = iter->second;
        if ((session->getBMCSessionID() != SESSION_ZERO) &&
            !(session->isSessionActive()))
        {
            iter = sessionsMap.erase(iter);
        }
        else
        {
            ++iter;
        }
    }
}

} // namespace session
