/*
// Copyright (c) 2018 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/

#include "channel_layer.hpp"

#include "channel_mgmt.hpp"
#include "cipher_mgmt.hpp"

#include <phosphor-logging/log.hpp>

namespace ipmi
{

bool doesDeviceExist(const uint8_t chNum)
{
    // TODO: This is not the reliable way to find the device
    // associated with ethernet interface as the channel number to
    // eth association is not done. Need to revisit later
    struct stat fileStat = {};
    std::string devName("/sys/class/net/" + getChannelName(chNum));

    if (stat(devName.data(), &fileStat) != 0)
    {
        phosphor::logging::log<phosphor::logging::level::DEBUG>(
            "Ethernet device not found");
        return false;
    }

    return true;
}

bool isValidPrivLimit(const uint8_t privLimit)
{
    // Callback privilege is deprecated in OpenBMC
    // At present, "OEM Privilege" is not used in OpenBMC
    return ((privLimit > PRIVILEGE_CALLBACK) && (privLimit < PRIVILEGE_OEM));
}

bool isValidAccessMode(const uint8_t accessMode)
{
    return (
        (accessMode >= static_cast<uint8_t>(EChannelAccessMode::disabled)) &&
        (accessMode <= static_cast<uint8_t>(EChannelAccessMode::shared)));
}

bool isValidChannel(const uint8_t chNum)
{
    return getChannelConfigObject().isValidChannel(chNum);
}

bool isValidAuthType(const uint8_t chNum, const EAuthType& authType)
{
    return getChannelConfigObject().isValidAuthType(chNum, authType);
}

EChannelSessSupported getChannelSessionSupport(const uint8_t chNum)
{
    return getChannelConfigObject().getChannelSessionSupport(chNum);
}

int getChannelActiveSessions(const uint8_t chNum)
{
    return getChannelConfigObject().getChannelActiveSessions(chNum);
}

size_t getChannelMaxTransferSize(uint8_t chNum)
{
    return getChannelConfigObject().getChannelMaxTransferSize(chNum);
}

Cc ipmiChannelInit()
{
    getChannelConfigObject();
    getCipherConfigObject(csPrivFileName, csPrivDefaultFileName);
    return ccSuccess;
}

Cc getChannelInfo(const uint8_t chNum, ChannelInfo& chInfo)
{
    return getChannelConfigObject().getChannelInfo(chNum, chInfo);
}

Cc getChannelAccessData(const uint8_t chNum, ChannelAccess& chAccessData)
{
    return getChannelConfigObject().getChannelAccessData(chNum, chAccessData);
}

Cc setChannelAccessData(const uint8_t chNum, const ChannelAccess& chAccessData,
                        const uint8_t setFlag)
{
    return getChannelConfigObject().setChannelAccessData(chNum, chAccessData,
                                                         setFlag);
}

Cc getChannelAccessPersistData(const uint8_t chNum, ChannelAccess& chAccessData)
{
    return getChannelConfigObject().getChannelAccessPersistData(chNum,
                                                                chAccessData);
}

Cc setChannelAccessPersistData(const uint8_t chNum,
                               const ChannelAccess& chAccessData,
                               const uint8_t setFlag)
{
    return getChannelConfigObject().setChannelAccessPersistData(
        chNum, chAccessData, setFlag);
}

Cc getChannelAuthTypeSupported(const uint8_t chNum, uint8_t& authTypeSupported)
{
    return getChannelConfigObject().getChannelAuthTypeSupported(
        chNum, authTypeSupported);
}

Cc getChannelEnabledAuthType(const uint8_t chNum, const uint8_t priv,
                             EAuthType& authType)
{
    return getChannelConfigObject().getChannelEnabledAuthType(chNum, priv,
                                                              authType);
}

std::string getChannelName(const uint8_t chNum)
{
    return getChannelConfigObject().getChannelName(chNum);
}

uint8_t getChannelByName(const std::string& chName)
{
    return getChannelConfigObject().getChannelByName(chName);
}

bool isValidPayloadType(const PayloadType payloadType)
{
    return (
        payloadType == PayloadType::IPMI || payloadType == PayloadType::SOL ||
        payloadType == PayloadType::OPEN_SESSION_REQUEST ||
        payloadType == PayloadType::OPEN_SESSION_RESPONSE ||
        payloadType == PayloadType::RAKP1 ||
        payloadType == PayloadType::RAKP2 ||
        payloadType == PayloadType::RAKP3 || payloadType == PayloadType::RAKP4);
}
} // namespace ipmi
