/*
// 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 <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/eth");
    devName += std::to_string(chNum - 1);

    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)
{
    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);
}

ipmi_ret_t ipmiChannelInit()
{
    getChannelConfigObject();
    return IPMI_CC_OK;
}

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

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

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

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

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

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

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

} // namespace ipmi
