/*
 *
 *    Copyright (c) 2021-2022 Project CHIP Authors
 *
 *    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.
 */

/**
 *    @file
 *          Utilities for accessing parameters of the network interface and the wireless
 *          statistics(extracted from /proc/net/wireless) on Linux platforms.
 */

#include <app-common/zap-generated/enums.h>
#include <platform/Linux/ConnectivityUtils.h>
#include <platform/internal/CHIPDeviceLayerInternal.h>

#include <arpa/inet.h>
#include <ifaddrs.h>
#include <linux/ethtool.h>
#include <linux/if_link.h>
#include <linux/sockios.h>
#include <linux/wireless.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#include <lib/core/CHIPEncoding.h>
#include <lib/support/CHIPMemString.h>
#include <lib/support/CodeUtils.h>

using namespace ::chip::app::Clusters::GeneralDiagnostics;

namespace chip {
namespace DeviceLayer {
namespace Internal {

uint16_t ConnectivityUtils::Map2400MHz(const uint8_t inChannel)
{
    uint16_t frequency = 0;

    if (inChannel >= 1 && inChannel <= 13)
    {
        frequency = static_cast<uint16_t>(2412 + ((inChannel - 1) * 5));
    }
    else if (inChannel == 14)
    {
        frequency = 2484;
    }

    return frequency;
}

uint16_t ConnectivityUtils::Map5000MHz(const uint8_t inChannel)
{
    uint16_t frequency = 0;

    switch (inChannel)
    {
    case 183:
        frequency = 4915;
        break;
    case 184:
        frequency = 4920;
        break;
    case 185:
        frequency = 4925;
        break;
    case 187:
        frequency = 4935;
        break;
    case 188:
        frequency = 4940;
        break;
    case 189:
        frequency = 4945;
        break;
    case 192:
        frequency = 4960;
        break;
    case 196:
        frequency = 4980;
        break;
    case 7:
        frequency = 5035;
        break;
    case 8:
        frequency = 5040;
        break;
    case 9:
        frequency = 5045;
        break;
    case 11:
        frequency = 5055;
        break;
    case 12:
        frequency = 5060;
        break;
    case 16:
        frequency = 5080;
        break;
    case 34:
        frequency = 5170;
        break;
    case 36:
        frequency = 5180;
        break;
    case 38:
        frequency = 5190;
        break;
    case 40:
        frequency = 5200;
        break;
    case 42:
        frequency = 5210;
        break;
    case 44:
        frequency = 5220;
        break;
    case 46:
        frequency = 5230;
        break;
    case 48:
        frequency = 5240;
        break;
    case 52:
        frequency = 5260;
        break;
    case 56:
        frequency = 5280;
        break;
    case 60:
        frequency = 5300;
        break;
    case 64:
        frequency = 5320;
        break;
    case 100:
        frequency = 5500;
        break;
    case 104:
        frequency = 5520;
        break;
    case 108:
        frequency = 5540;
        break;
    case 112:
        frequency = 5560;
        break;
    case 116:
        frequency = 5580;
        break;
    case 120:
        frequency = 5600;
        break;
    case 124:
        frequency = 5620;
        break;
    case 128:
        frequency = 5640;
        break;
    case 132:
        frequency = 5660;
        break;
    case 136:
        frequency = 5680;
        break;
    case 140:
        frequency = 5700;
        break;
    case 149:
        frequency = 5745;
        break;
    case 153:
        frequency = 5765;
        break;
    case 157:
        frequency = 5785;
        break;
    case 161:
        frequency = 5805;
        break;
    case 165:
        frequency = 5825;
        break;
    }

    return frequency;
}

uint16_t ConnectivityUtils::MapChannelToFrequency(const uint16_t inBand, const uint8_t inChannel)
{
    uint16_t frequency = 0;

    if (inBand == kWiFi_BAND_2_4_GHZ)
    {
        frequency = Map2400MHz(inChannel);
    }
    else if (inBand == kWiFi_BAND_5_0_GHZ)
    {
        frequency = Map5000MHz(inChannel);
    }

    return frequency;
}

uint8_t ConnectivityUtils::MapFrequencyToChannel(const uint16_t frequency)
{
    if (frequency < 2412)
        return 0;

    if (frequency < 2484)
        return (frequency - 2407) / 5;

    if (frequency == 2484)
        return 14;

    return frequency / 5 - 1000;
}

double ConnectivityUtils::ConvertFrequenceToFloat(const iw_freq * in)
{
    double result = (double) in->m;

    for (int i = 0; i < in->e; i++)
        result *= 10;

    return result;
}

InterfaceType ConnectivityUtils::GetInterfaceConnectionType(const char * ifname)
{
    InterfaceType ret = InterfaceType::EMBER_ZCL_INTERFACE_TYPE_UNSPECIFIED;
    int sock          = -1;

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        ChipLogError(DeviceLayer, "Failed to open socket");
        return InterfaceType::EMBER_ZCL_INTERFACE_TYPE_UNSPECIFIED;
    }

    // Test wireless extensions for CONNECTION_WIFI
    struct iwreq pwrq = {};
    Platform::CopyString(pwrq.ifr_name, ifname);

    if (ioctl(sock, SIOCGIWNAME, &pwrq) != -1)
    {
        ret = InterfaceType::EMBER_ZCL_INTERFACE_TYPE_WI_FI;
    }
    else if ((strncmp(ifname, "en", 2) == 0) || (strncmp(ifname, "eth", 3) == 0))
    {
        struct ethtool_cmd ecmd = {};
        ecmd.cmd                = ETHTOOL_GSET;
        struct ifreq ifr        = {};
        ifr.ifr_data            = reinterpret_cast<char *>(&ecmd);
        Platform::CopyString(ifr.ifr_name, ifname);

        if (ioctl(sock, SIOCETHTOOL, &ifr) != -1)
            ret = InterfaceType::EMBER_ZCL_INTERFACE_TYPE_ETHERNET;
    }

    close(sock);

    return ret;
}

CHIP_ERROR ConnectivityUtils::GetInterfaceHardwareAddrs(const char * ifname, uint8_t * buf, size_t bufSize)
{
    CHIP_ERROR err = CHIP_ERROR_READ_FAILED;
    int skfd;

    if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        ChipLogError(DeviceLayer, "Failed to create a channel to the NET kernel.");
        return CHIP_ERROR_OPEN_FAILED;
    }

    if (ifname[0] != '\0')
    {
        struct ifreq req;

        strcpy(req.ifr_name, ifname);
        if (ioctl(skfd, SIOCGIFHWADDR, &req) != -1)
        {
            // Copy 48-bit IEEE MAC Address
            VerifyOrReturnError(bufSize >= 6, CHIP_ERROR_BUFFER_TOO_SMALL);

            memset(buf, 0, bufSize);
            memcpy(buf, req.ifr_ifru.ifru_hwaddr.sa_data, 6);
            err = CHIP_NO_ERROR;
        }
    }

    close(skfd);

    return err;
}

CHIP_ERROR ConnectivityUtils::GetInterfaceIPv4Addrs(const char * ifname, uint8_t & size, NetworkInterface * ifp)
{
    CHIP_ERROR err;
    struct ifaddrs * ifaddr = nullptr;

    if (getifaddrs(&ifaddr) == -1)
    {
        ChipLogError(DeviceLayer, "Failed to get network interfaces");
        err = CHIP_ERROR_READ_FAILED;
    }
    else
    {
        uint8_t index = 0;

        for (struct ifaddrs * ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
        {
            if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET)
            {
                if (strcmp(ifname, ifa->ifa_name) == 0)
                {
                    void * addPtr = &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr;

                    memcpy(ifp->Ipv4AddressesBuffer[index], addPtr, kMaxIPv4AddrSize);
                    ifp->Ipv4AddressSpans[index] = ByteSpan(ifp->Ipv4AddressesBuffer[index], kMaxIPv4AddrSize);
                    index++;

                    if (index >= kMaxIPv4AddrCount)
                    {
                        break;
                    }
                }
            }
        }

        if (index > 0)
        {
            err  = CHIP_NO_ERROR;
            size = index;
        }

        freeifaddrs(ifaddr);
    }

    return err;
}

CHIP_ERROR ConnectivityUtils::GetInterfaceIPv6Addrs(const char * ifname, uint8_t & size, NetworkInterface * ifp)
{
    CHIP_ERROR err;
    struct ifaddrs * ifaddr = nullptr;

    if (getifaddrs(&ifaddr) == -1)
    {
        ChipLogError(DeviceLayer, "Failed to get network interfaces");
        err = CHIP_ERROR_READ_FAILED;
    }
    else
    {
        uint8_t index = 0;

        for (struct ifaddrs * ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
        {
            if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET6)
            {
                if (strcmp(ifname, ifa->ifa_name) == 0)
                {
                    void * addPtr = &((struct sockaddr_in6 *) ifa->ifa_addr)->sin6_addr;

                    memcpy(ifp->Ipv6AddressesBuffer[index], addPtr, kMaxIPv6AddrSize);
                    ifp->Ipv6AddressSpans[index] = ByteSpan(ifp->Ipv6AddressesBuffer[index], kMaxIPv6AddrSize);
                    index++;

                    if (index >= kMaxIPv6AddrCount)
                    {
                        break;
                    }
                }
            }
        }

        if (index > 0)
        {
            err  = CHIP_NO_ERROR;
            size = index;
        }

        freeifaddrs(ifaddr);
    }

    return err;
}

CHIP_ERROR ConnectivityUtils::GetWiFiInterfaceName(char * ifname, size_t bufSize)
{
    CHIP_ERROR err          = CHIP_ERROR_READ_FAILED;
    struct ifaddrs * ifaddr = nullptr;

    if (getifaddrs(&ifaddr) == -1)
    {
        ChipLogError(DeviceLayer, "Failed to get network interfaces");
    }
    else
    {
        struct ifaddrs * ifa = nullptr;

        /* Walk through linked list, maintaining head pointer so we
          can free list later */
        for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
        {
            if (GetInterfaceConnectionType(ifa->ifa_name) == InterfaceType::EMBER_ZCL_INTERFACE_TYPE_WI_FI)
            {
                Platform::CopyString(ifname, bufSize, ifa->ifa_name);
                err = CHIP_NO_ERROR;
                break;
            }
        }

        freeifaddrs(ifaddr);
    }

    return err;
}

CHIP_ERROR ConnectivityUtils::GetWiFiParameter(int skfd,            /* Socket to the kernel */
                                               const char * ifname, /* Device name */
                                               int request,         /* WE ID */
                                               struct iwreq * pwrq) /* Fixed part of the request */
{
    /* Set device name */
    Platform::CopyString(pwrq->ifr_name, ifname);

    /* Do the request */
    if (ioctl(skfd, request, pwrq) < 0)
    {
        return CHIP_ERROR_BAD_REQUEST;
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR ConnectivityUtils::GetWiFiStats(int skfd, const char * ifname, struct iw_statistics * stats)
{
    struct iwreq wrq;

    wrq.u.data.pointer = (caddr_t) stats;
    wrq.u.data.length  = sizeof(struct iw_statistics);
    wrq.u.data.flags   = 1; /*Clear updated flag */
    Platform::CopyString(wrq.ifr_name, ifname);

    return GetWiFiParameter(skfd, ifname, SIOCGIWSTATS, &wrq);
}

CHIP_ERROR ConnectivityUtils::GetWiFiChannelNumber(const char * ifname, uint16_t & channelNumber)
{
    CHIP_ERROR err = CHIP_ERROR_READ_FAILED;

    struct iwreq wrq;
    int skfd;

    if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        ChipLogError(DeviceLayer, "Failed to create a channel to the NET kernel.");
        return CHIP_ERROR_OPEN_FAILED;
    }

    if (GetWiFiParameter(skfd, ifname, SIOCGIWFREQ, &wrq) == CHIP_NO_ERROR)
    {
        double freq = ConvertFrequenceToFloat(&(wrq.u.freq));
        VerifyOrReturnError((freq / 1000000) <= UINT16_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
        channelNumber = MapFrequencyToChannel(static_cast<uint16_t>(freq / 1000000));

        err = CHIP_NO_ERROR;
    }

    close(skfd);

    return err;
}

CHIP_ERROR ConnectivityUtils::GetWiFiRssi(const char * ifname, int8_t & rssi)
{
    CHIP_ERROR err = CHIP_ERROR_READ_FAILED;
    struct iw_statistics stats;
    int skfd;

    if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        ChipLogError(DeviceLayer, "Failed to create a channel to the NET kernel.");
        return CHIP_ERROR_OPEN_FAILED;
    }

    if (GetWiFiStats(skfd, ifname, &stats) == CHIP_NO_ERROR)
    {
        struct iw_quality * qual = &stats.qual;

        /* Check if the statistics are in RCPI (IEEE 802.11k) */
        if (qual->updated & IW_QUAL_RCPI)
        { /* Deal with signal level in RCPI */
            /* RCPI = int{(Power in dBm +110)*2} for 0dbm > Power > -110dBm */
            if (!(qual->updated & IW_QUAL_LEVEL_INVALID))
            {
                double rcpilevel = (qual->level / 2.0) - 110.0;
                VerifyOrReturnError(rcpilevel <= INT8_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
                rssi = static_cast<int8_t>(rcpilevel);
                err  = CHIP_NO_ERROR;
            }
        }
        else
        { /* Check if the statistics are in dBm */
            if (qual->updated & IW_QUAL_DBM)
            { /* Deal with signal level in dBm  (absolute power measurement) */
                if (!(qual->updated & IW_QUAL_LEVEL_INVALID))
                {
                    int dblevel = qual->level;
                    /* Implement a range for dBm[-192; 63] */
                    if (qual->level >= 64)
                        dblevel -= 0x100;

                    VerifyOrReturnError(dblevel <= INT8_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
                    rssi = static_cast<int8_t>(dblevel);
                    err  = CHIP_NO_ERROR;
                }
            }
            else
            { /* Deal with signal level as relative value (0 -> max) */
                if (!(qual->updated & IW_QUAL_LEVEL_INVALID))
                {
                    VerifyOrReturnError(qual->level <= INT8_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
                    rssi = static_cast<int8_t>(qual->level);
                    err  = CHIP_NO_ERROR;
                }
            }
        }
    }

    close(skfd);

    return err;
}

CHIP_ERROR ConnectivityUtils::GetWiFiBeaconLostCount(const char * ifname, uint32_t & beaconLostCount)
{
    CHIP_ERROR err = CHIP_ERROR_READ_FAILED;
    struct iw_statistics stats;
    int skfd;

    if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        ChipLogError(DeviceLayer, "Failed to create a channel to the NET kernel.");
        return CHIP_ERROR_OPEN_FAILED;
    }

    if (GetWiFiStats(skfd, ifname, &stats) == CHIP_NO_ERROR)
    {
        beaconLostCount = stats.miss.beacon;
        err             = CHIP_NO_ERROR;
    }

    close(skfd);

    return err;
}

CHIP_ERROR ConnectivityUtils::GetWiFiCurrentMaxRate(const char * ifname, uint64_t & currentMaxRate)
{
    CHIP_ERROR err = CHIP_ERROR_READ_FAILED;
    struct iwreq wrq;
    int skfd;

    if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        ChipLogError(DeviceLayer, "Failed to create a channel to the NET kernel.");
        return CHIP_ERROR_OPEN_FAILED;
    }

    if (GetWiFiParameter(skfd, ifname, SIOCGIWRATE, &wrq) == CHIP_NO_ERROR)
    {
        currentMaxRate = wrq.u.bitrate.value;
        err            = CHIP_NO_ERROR;
    }

    close(skfd);

    return err;
}

CHIP_ERROR ConnectivityUtils::GetEthInterfaceName(char * ifname, size_t bufSize)
{
    CHIP_ERROR err          = CHIP_ERROR_READ_FAILED;
    struct ifaddrs * ifaddr = nullptr;

    if (getifaddrs(&ifaddr) == -1)
    {
        ChipLogError(DeviceLayer, "Failed to get network interfaces");
    }
    else
    {
        struct ifaddrs * ifa = nullptr;

        /* Walk through linked list, maintaining head pointer so we
          can free list later */
        for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
        {
            if (GetInterfaceConnectionType(ifa->ifa_name) == InterfaceType::EMBER_ZCL_INTERFACE_TYPE_ETHERNET)
            {
                Platform::CopyString(ifname, bufSize, ifa->ifa_name);
                err = CHIP_NO_ERROR;
                break;
            }
        }

        freeifaddrs(ifaddr);
    }

    return err;
}

CHIP_ERROR ConnectivityUtils::GetEthPHYRate(const char * ifname, app::Clusters::EthernetNetworkDiagnostics::PHYRateType & pHYRate)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    int skfd;
    uint32_t speed          = 0;
    struct ethtool_cmd ecmd = {};
    ecmd.cmd                = ETHTOOL_GSET;
    struct ifreq ifr        = {};

    ifr.ifr_data = reinterpret_cast<char *>(&ecmd);
    Platform::CopyString(ifr.ifr_name, ifname);

    if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        ChipLogError(DeviceLayer, "Failed to create a channel to the NET kernel.");
        return CHIP_ERROR_OPEN_FAILED;
    }

    if (ioctl(skfd, SIOCETHTOOL, &ifr) == -1)
    {
        ChipLogError(DeviceLayer, "Cannot get device settings");
        close(skfd);
        return CHIP_ERROR_READ_FAILED;
    }

    speed = (ecmd.speed_hi << 16) | ecmd.speed;
    switch (speed)
    {
    case 10:
        pHYRate = EmberAfPHYRateType::EMBER_ZCL_PHY_RATE_TYPE_10_M;
        break;
    case 100:
        pHYRate = EmberAfPHYRateType::EMBER_ZCL_PHY_RATE_TYPE_100_M;
        break;
    case 1000:
        pHYRate = EmberAfPHYRateType::EMBER_ZCL_PHY_RATE_TYPE_1000_M;
        break;
    case 25000:
        pHYRate = EmberAfPHYRateType::EMBER_ZCL_PHY_RATE_TYPE_2__5_G;
        break;
    case 5000:
        pHYRate = EmberAfPHYRateType::EMBER_ZCL_PHY_RATE_TYPE_5_G;
        break;
    case 10000:
        pHYRate = EmberAfPHYRateType::EMBER_ZCL_PHY_RATE_TYPE_10_G;
        break;
    case 40000:
        pHYRate = EmberAfPHYRateType::EMBER_ZCL_PHY_RATE_TYPE_40_G;
        break;
    case 100000:
        pHYRate = EmberAfPHYRateType::EMBER_ZCL_PHY_RATE_TYPE_100_G;
        break;
    case 200000:
        pHYRate = EmberAfPHYRateType::EMBER_ZCL_PHY_RATE_TYPE_200_G;
        break;
    case 400000:
        pHYRate = EmberAfPHYRateType::EMBER_ZCL_PHY_RATE_TYPE_400_G;
        break;
    default:
        ChipLogError(DeviceLayer, "Undefined speed! (%d)\n", speed);
        err = CHIP_ERROR_READ_FAILED;
        break;
    };

    close(skfd);

    return err;
}

CHIP_ERROR ConnectivityUtils::GetEthFullDuplex(const char * ifname, bool & fullDuplex)
{
    CHIP_ERROR err = CHIP_ERROR_READ_FAILED;

    int skfd;
    struct ethtool_cmd ecmd = {};
    ecmd.cmd                = ETHTOOL_GSET;
    struct ifreq ifr        = {};

    ifr.ifr_data = reinterpret_cast<char *>(&ecmd);
    Platform::CopyString(ifr.ifr_name, ifname);

    if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        ChipLogError(DeviceLayer, "Failed to create a channel to the NET kernel.");
        return CHIP_ERROR_OPEN_FAILED;
    }

    if (ioctl(skfd, SIOCETHTOOL, &ifr) == -1)
    {
        ChipLogError(DeviceLayer, "Cannot get device settings");
        err = CHIP_ERROR_READ_FAILED;
    }
    else
    {
        fullDuplex = ecmd.duplex == DUPLEX_FULL;
        err        = CHIP_NO_ERROR;
    }

    close(skfd);

    return err;
}

} // namespace Internal
} // namespace DeviceLayer
} // namespace chip
