#include <phosphor-logging/log.hpp>
#include "main.hpp"
#include "sol/sol_context.hpp"
#include "sol/sol_manager.hpp"
#include "sol_cmds.hpp"

namespace sol
{

namespace command
{

using namespace phosphor::logging;

std::vector<uint8_t> payloadHandler(const std::vector<uint8_t>& inPayload,
                                    const message::Handler& handler)
{
    auto request = reinterpret_cast<const Payload*>(inPayload.data());
    auto solDataSize = inPayload.size() - sizeof(Payload);

    Buffer charData(solDataSize);
    if( solDataSize > 0)
    {
        std::copy_n(inPayload.data() + sizeof(Payload),
                    solDataSize,
                    charData.begin());
    }

    try
    {
        auto& context = std::get<sol::Manager&>(singletonPool).
                getContext(handler.sessionID);

        context.processInboundPayload(request->packetSeqNum,
                                      request->packetAckSeqNum,
                                      request->acceptedCharCount,
                                      request->inOperation.ack,
                                      charData);
    }
    catch (std::exception& e)
    {
        log<level::ERR>(e.what());
        return std::vector<uint8_t>();
    }

    return std::vector<uint8_t>();
}

void activating(uint8_t payloadInstance, uint32_t sessionID)
{
    std::vector<uint8_t> outPayload(sizeof(ActivatingRequest));

    auto request = reinterpret_cast<ActivatingRequest*>
                    (outPayload.data());

    request->sessionState = 0;
    request->payloadInstance = payloadInstance;
    request->majorVersion = MAJOR_VERSION;
    request->minorVersion = MINOR_VERSION;

    auto session = (std::get<session::Manager&>(singletonPool).getSession(
            sessionID)).lock();

    message::Handler msgHandler(session->channelPtr, sessionID);

    msgHandler.sendUnsolicitedIPMIPayload(netfnTransport,
                                          solActivatingCmd,
                                          outPayload);
}

std::vector<uint8_t> setConfParams(const std::vector<uint8_t>& inPayload,
                                   const message::Handler& handler)
{
    std::vector<uint8_t> outPayload(sizeof(SetConfParamsResponse));
    auto request = reinterpret_cast<const SetConfParamsRequest*>
                   (inPayload.data());
    auto response = reinterpret_cast<SetConfParamsResponse*>
                    (outPayload.data());
    response->completionCode = IPMI_CC_OK;

    switch (static_cast<Parameter>(request->paramSelector))
    {
        case Parameter::PROGRESS:
        {
            uint8_t progress = request->value & progressMask;
            std::get<sol::Manager&>(singletonPool).progress = progress;
            break;
        }
        case Parameter::ENABLE:
        {
            bool enable = request->value & enableMask;
            std::get<sol::Manager&>(singletonPool).enable = enable;
            break;
        }
        case Parameter::AUTHENTICATION:
        {
            if (!request->auth.auth || !request->auth.encrypt)
            {
                response->completionCode = ipmiCCWriteReadParameter;
            }
            else if (request->auth.privilege <
                     static_cast<uint8_t>(session::Privilege::USER) ||
                     request->auth.privilege >
                     static_cast<uint8_t>(session::Privilege::OEM))
            {
                response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
            }
            else
            {
                std::get<sol::Manager&>(singletonPool).solMinPrivilege =
                       static_cast<session::Privilege>(request->auth.privilege);
            }
            break;
        }
        case Parameter::ACCUMULATE:
        {
            using namespace std::chrono_literals;

            if (request->acc.threshold == 0)
            {
                response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
                break;
            }

            std::get<sol::Manager&>(singletonPool).accumulateInterval =
                    request->acc.interval * sol::accIntervalFactor * 1ms;
            std::get<sol::Manager&>(singletonPool).sendThreshold =
                    request->acc.threshold;
            break;
        }
        case Parameter::RETRY:
        {
            using namespace std::chrono_literals;

            std::get<sol::Manager&>(singletonPool).retryCount =
                    request->retry.count;
            std::get<sol::Manager&>(singletonPool).retryInterval =
                    request->retry.interval * sol::retryIntervalFactor * 1ms;
            break;
        }
        case Parameter::PORT:
        {
            response->completionCode = ipmiCCWriteReadParameter;
            break;
        }
        case Parameter::NVBITRATE:
        case Parameter::VBITRATE:
        case Parameter::CHANNEL:
        default:
            response->completionCode = ipmiCCParamNotSupported;
    }

    return outPayload;
}

std::vector<uint8_t> getConfParams(const std::vector<uint8_t>& inPayload,
                                   const message::Handler& handler)
{
    std::vector<uint8_t> outPayload(sizeof(GetConfParamsResponse));
    auto request = reinterpret_cast<const GetConfParamsRequest*>
                   (inPayload.data());
    auto response = reinterpret_cast<GetConfParamsResponse*>
                    (outPayload.data());
    response->completionCode = IPMI_CC_OK;
    response->paramRev = parameterRevision;

    if (request->getParamRev)
    {
        return outPayload;
    }

    switch (static_cast<Parameter>(request->paramSelector))
    {
        case Parameter::PROGRESS:
        {
            outPayload.push_back(std::get<sol::Manager&>
                    (singletonPool).progress);
            break;
        }
        case Parameter::ENABLE:
        {
            outPayload.push_back(std::get<sol::Manager&>
                    (singletonPool).enable);
            break;
        }
        case Parameter::AUTHENTICATION:
        {
            Auth value {0};

            value.encrypt = std::get<sol::Manager&>(singletonPool).forceEncrypt;
            value.auth = std::get<sol::Manager&>(singletonPool).forceAuth;
            value.privilege  = static_cast<uint8_t>(std::get<sol::Manager&>
                    (singletonPool).solMinPrivilege);
            auto buffer = reinterpret_cast<const uint8_t *>(&value);

            std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
            break;
        }
        case Parameter::ACCUMULATE:
        {
            Accumulate value {0};

            value.interval = std::get<sol::Manager&>(singletonPool)
                            .accumulateInterval.count()/sol::accIntervalFactor;
            value.threshold = std::get<sol::Manager&>
                            (singletonPool).sendThreshold;
            auto buffer = reinterpret_cast<const uint8_t *>(&value);

            std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
            break;
        }
        case Parameter::RETRY:
        {
            Retry value {0};

            value.count = std::get<sol::Manager&>(singletonPool).retryCount;
            value.interval = std::get<sol::Manager&>(singletonPool)
                    .retryInterval.count()/sol::retryIntervalFactor;
            auto buffer = reinterpret_cast<const uint8_t *>(&value);

            std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
            break;
        }
        case Parameter::PORT:
        {
            auto port = endian::to_ipmi<uint16_t>(IPMI_STD_PORT);
            auto buffer = reinterpret_cast<const uint8_t *>(&port);

            std::copy_n(buffer, sizeof(port), std::back_inserter(outPayload));
            break;
        }
        case Parameter::NVBITRATE:
        case Parameter::VBITRATE:
        case Parameter::CHANNEL:
        default:
            response->completionCode = ipmiCCParamNotSupported;
    }

    return outPayload;
}

} // namespace command

} // namespace sol
