/*
 *
 *    Copyright (c) 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
 *          Provides the wrapper for nRF WiFi API
 */

#include "WiFiManager.h"

#include <inet/InetInterface.h>
#include <inet/UDPEndPointImplSockets.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/Zephyr/InetUtils.h>

#include <net/net_stats.h>
#include <zephyr.h>

extern "C" {
#include <common/defs.h>
#include <wpa_supplicant/config.h>
#include <wpa_supplicant/driver_i.h>
#include <wpa_supplicant/scan.h>
#include <zephyr/net/wifi_mgmt.h>
}

extern struct wpa_global * global;

static struct wpa_supplicant * wpa_s;

namespace chip {
namespace DeviceLayer {

namespace {

NetworkCommissioning::WiFiScanResponse ToScanResponse(wifi_scan_result * result)
{
    NetworkCommissioning::WiFiScanResponse response = {};

    if (result != nullptr)
    {
        static_assert(sizeof(response.ssid) == sizeof(result->ssid), "SSID length mismatch");
        static_assert(sizeof(response.bssid) == sizeof(result->mac), "BSSID length mismatch");

        // TODO: Distinguish WPA versions
        response.security.Set(result->security == WIFI_SECURITY_TYPE_PSK ? NetworkCommissioning::WiFiSecurity::kWpaPersonal
                                                                         : NetworkCommissioning::WiFiSecurity::kUnencrypted);
        response.channel = result->channel;
        response.rssi    = result->rssi;
        response.ssidLen = result->ssid_length;
        memcpy(response.ssid, result->ssid, result->ssid_length);
        // TODO: MAC/BSSID is not filled by the Wi-Fi driver
        memcpy(response.bssid, result->mac, result->mac_length);
    }

    return response;
}

} // namespace

// These enums shall reflect the overall ordered disconnected->connected flow
const Map<wpa_states, WiFiManager::StationStatus, 10>
    WiFiManager::sStatusMap({ { WPA_DISCONNECTED, WiFiManager::StationStatus::DISCONNECTED },
                              { WPA_INTERFACE_DISABLED, WiFiManager::StationStatus::DISABLED },
                              { WPA_INACTIVE, WiFiManager::StationStatus::DISABLED },
                              { WPA_SCANNING, WiFiManager::StationStatus::SCANNING },
                              { WPA_AUTHENTICATING, WiFiManager::StationStatus::CONNECTING },
                              { WPA_ASSOCIATING, WiFiManager::StationStatus::CONNECTING },
                              { WPA_ASSOCIATED, WiFiManager::StationStatus::CONNECTED },
                              { WPA_4WAY_HANDSHAKE, WiFiManager::StationStatus::PROVISIONING },
                              { WPA_GROUP_HANDSHAKE, WiFiManager::StationStatus::PROVISIONING },
                              { WPA_COMPLETED, WiFiManager::StationStatus::FULLY_PROVISIONED } });

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

CHIP_ERROR WiFiManager::Init()
{
    // wpa_supplicant instance is initialized in dedicated supplicant thread, so wait until
    // the initialization is completed.
    // TODO: fix thread-safety of the solution.
    constexpr size_t kInitTimeoutMs = 5000;
    const int64_t initStartTime     = k_uptime_get();
    // TODO: Handle multiple VIFs
    const char * ifname = "wlan0";

    while (!global || !(wpa_s = wpa_supplicant_get_iface(global, ifname)))
    {
        if (k_uptime_get() > initStartTime + kInitTimeoutMs)
        {
            ChipLogError(DeviceLayer, "wpa_supplicant is not initialized!");
            return CHIP_ERROR_INTERNAL;
        }

        k_msleep(200);
    }

    // TODO: consider moving these to ConnectivityManagerImpl to be prepared for handling multiple interfaces on a single device.
    Inet::UDPEndPointImplSockets::SetJoinMulticastGroupHandler([](Inet::InterfaceId interfaceId, const Inet::IPAddress & address) {
        const in6_addr addr = InetUtils::ToZephyrAddr(address);
        net_if * iface      = InetUtils::GetInterface(interfaceId);
        VerifyOrReturnError(iface != nullptr, INET_ERROR_UNKNOWN_INTERFACE);

        net_if_mcast_addr * maddr = net_if_ipv6_maddr_add(iface, &addr);

        if (maddr && !net_if_ipv6_maddr_is_joined(maddr) && !net_ipv6_is_addr_mcast_link_all_nodes(&addr))
        {
            net_if_ipv6_maddr_join(maddr);
        }

        return CHIP_NO_ERROR;
    });

    Inet::UDPEndPointImplSockets::SetLeaveMulticastGroupHandler([](Inet::InterfaceId interfaceId, const Inet::IPAddress & address) {
        const in6_addr addr = InetUtils::ToZephyrAddr(address);
        net_if * iface      = InetUtils::GetInterface(interfaceId);
        VerifyOrReturnError(iface != nullptr, INET_ERROR_UNKNOWN_INTERFACE);

        if (!net_ipv6_is_addr_mcast_link_all_nodes(&addr) && !net_if_ipv6_maddr_rm(iface, &addr))
        {
            return CHIP_ERROR_INVALID_ADDRESS;
        }

        return CHIP_NO_ERROR;
    });

    ChipLogDetail(DeviceLayer, "wpa_supplicant has been initialized");

    return CHIP_NO_ERROR;
}

CHIP_ERROR WiFiManager::AddNetwork(const ByteSpan & ssid, const ByteSpan & credentials)
{
    ChipLogDetail(DeviceLayer, "Adding WiFi network");
    mpWpaNetwork = wpa_supplicant_add_network(wpa_s);
    if (mpWpaNetwork)
    {
        static constexpr size_t kMaxSsidLen{ 32 };
        mpWpaNetwork->ssid = (u8 *) k_malloc(kMaxSsidLen);

        if (mpWpaNetwork->ssid)
        {
            memcpy(mpWpaNetwork->ssid, ssid.data(), ssid.size());
            mpWpaNetwork->ssid_len    = ssid.size();
            mpWpaNetwork->key_mgmt    = WPA_KEY_MGMT_NONE;
            mpWpaNetwork->disabled    = 1;
            wpa_s->conf->filter_ssids = 1;

            return AddPsk(credentials);
        }
    }

    return CHIP_ERROR_INTERNAL;
}

CHIP_ERROR WiFiManager::Scan(const ByteSpan & ssid, ScanCallback callback)
{
    const StationStatus stationStatus = GetStationStatus();
    VerifyOrReturnError(stationStatus != StationStatus::DISABLED && stationStatus != StationStatus::SCANNING &&
                            stationStatus != StationStatus::CONNECTING,
                        CHIP_ERROR_INCORRECT_STATE);

    net_if * const iface = InetUtils::GetInterface();
    VerifyOrReturnError(iface != nullptr, CHIP_ERROR_INTERNAL);

    const device * dev = net_if_get_device(iface);
    VerifyOrReturnError(dev != nullptr, CHIP_ERROR_INTERNAL);

    const net_wifi_mgmt_offload * ops = static_cast<const net_wifi_mgmt_offload *>(dev->api);
    VerifyOrReturnError(ops != nullptr, CHIP_ERROR_INTERNAL);

    mScanCallback = callback;

    // TODO: Use saner API once such exists.
    // TODO: Take 'ssid' into account.
    VerifyOrReturnError(ops->scan(dev,
                                  [](net_if *, int status, wifi_scan_result * result) {
                                      VerifyOrReturn(Instance().mScanCallback != nullptr);
                                      NetworkCommissioning::WiFiScanResponse response = ToScanResponse(result);
                                      Instance().mScanCallback(status, result != nullptr ? &response : nullptr);
                                  }) == 0,
                        CHIP_ERROR_INTERNAL);

    return CHIP_NO_ERROR;
}

CHIP_ERROR WiFiManager::Connect(const ByteSpan & ssid, const ByteSpan & credentials, const ConnectionHandling & handling)
{
    ChipLogDetail(DeviceLayer, "Connecting to WiFi network");

    mConnectionSuccessClbk = handling.mOnConnectionSuccess;
    mConnectionFailedClbk  = handling.mOnConnectionFailed;
    mConnectionTimeoutMs   = handling.mConnectionTimeoutMs;

    CHIP_ERROR err = AddNetwork(ssid, credentials);
    if (CHIP_NO_ERROR == err)
    {
        EnableStation(true);
        wpa_supplicant_select_network(wpa_s, mpWpaNetwork);
        WaitForConnectionAsync();
    }
    else
    {
        OnConnectionFailed();
    }
    return err;
}

void WiFiManager::OnConnectionSuccess()
{
    if (mConnectionSuccessClbk)
        mConnectionSuccessClbk();
}

void WiFiManager::OnConnectionFailed()
{
    if (mConnectionFailedClbk)
        mConnectionFailedClbk();
}

CHIP_ERROR WiFiManager::AddPsk(const ByteSpan & credentials)
{
    mpWpaNetwork->key_mgmt = WPA_KEY_MGMT_PSK;
    str_clear_free(mpWpaNetwork->passphrase);
    mpWpaNetwork->passphrase = dup_binstr(credentials.data(), credentials.size());

    if (mpWpaNetwork->passphrase)
    {
        wpa_config_update_psk(mpWpaNetwork);
        return CHIP_NO_ERROR;
    }

    return CHIP_ERROR_INTERNAL;
}

WiFiManager::StationStatus WiFiManager::GetStationStatus() const
{
    if (wpa_s)
    {
        return StatusFromWpaStatus(wpa_s->wpa_state);
    }
    else
    {
        ChipLogError(DeviceLayer, "wpa_supplicant is not initialized!");
        return StationStatus::NONE;
    }
}

WiFiManager::StationStatus WiFiManager::StatusFromWpaStatus(const wpa_states & status)
{
    ChipLogDetail(DeviceLayer, "WPA internal status: %d", static_cast<int>(status));
    return WiFiManager::sStatusMap[status];
}

CHIP_ERROR WiFiManager::EnableStation(bool enable)
{
    VerifyOrReturnError(nullptr != wpa_s && nullptr != mpWpaNetwork, CHIP_ERROR_INTERNAL);
    if (enable)
    {
        wpa_supplicant_enable_network(wpa_s, mpWpaNetwork);
    }
    else
    {
        wpa_supplicant_disable_network(wpa_s, mpWpaNetwork);
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR WiFiManager::ClearStationProvisioningData()
{
    VerifyOrReturnError(nullptr != wpa_s && nullptr != mpWpaNetwork, CHIP_ERROR_INTERNAL);
    wpa_supplicant_cancel_scan(wpa_s);
    wpa_clear_keys(wpa_s, mpWpaNetwork->bssid);
    str_clear_free(mpWpaNetwork->passphrase);
    wpa_config_update_psk(mpWpaNetwork);
    wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);

    return CHIP_NO_ERROR;
}

CHIP_ERROR WiFiManager::DisconnectStation()
{
    VerifyOrReturnError(nullptr != wpa_s, CHIP_ERROR_INTERNAL);
    wpa_supplicant_cancel_scan(wpa_s);
    wpas_request_disconnection(wpa_s);

    return CHIP_NO_ERROR;
}

void WiFiManager::WaitForConnectionAsync()
{
    chip::DeviceLayer::SystemLayer().StartTimer(
        static_cast<System::Clock::Timeout>(1000), [](System::Layer *, void *) { Instance().PollTimerCallback(); }, nullptr);
}

void WiFiManager::PollTimerCallback()
{
    const uint32_t kMaxRetriesNumber{ mConnectionTimeoutMs.count() / 1000 };
    static uint32_t retriesNumber{ 0 };

    if (WiFiManager::StationStatus::FULLY_PROVISIONED == GetStationStatus())
    {
        retriesNumber = 0;
        OnConnectionSuccess();
    }
    else
    {
        if (retriesNumber++ < kMaxRetriesNumber)
        {
            // wait more time
            WaitForConnectionAsync();
        }
        else
        {
            // connection timeout
            retriesNumber = 0;
            OnConnectionFailed();
        }
    }
}

CHIP_ERROR WiFiManager::GetWiFiInfo(WiFiInfo & info) const
{
    VerifyOrReturnError(nullptr != wpa_s, CHIP_ERROR_INTERNAL);
    VerifyOrReturnError(nullptr != mpWpaNetwork, CHIP_ERROR_INTERNAL);

    static uint8_t sBssid[ETH_ALEN];
    if (WiFiManager::StationStatus::CONNECTED <= GetStationStatus())
    {
        memcpy(sBssid, wpa_s->bssid, ETH_ALEN);
        info.mBssId        = ByteSpan(sBssid, ETH_ALEN);
        info.mSecurityType = GetSecurityType();
        // TODO: this should reflect the real connection compliance
        // i.e. the AP might support WiFi 5 only even though the station
        // is WiFi 6 ready (so the connection is WiFi 5 effectively).
        // For now just return what the station supports.
        info.mWiFiVersion = EMBER_ZCL_WI_FI_VERSION_TYPE_802__11AX;

        wpa_signal_info signalInfo{};
        if (0 == wpa_drv_signal_poll(wpa_s, &signalInfo))
        {
            info.mRssi    = signalInfo.current_signal; // dBm
            info.mChannel = FrequencyToChannel(signalInfo.frequency);
        }
        else
        {
            // this values should be nullable according to the Matter spec
            info.mRssi    = std::numeric_limits<decltype(info.mRssi)>::min();
            info.mChannel = std::numeric_limits<decltype(info.mChannel)>::min();
        }

        memcpy(info.mSsid, mpWpaNetwork->ssid, mpWpaNetwork->ssid_len);
        info.mSsidLen = mpWpaNetwork->ssid_len;

        return CHIP_NO_ERROR;
    }

    return CHIP_ERROR_INTERNAL;
}

uint8_t WiFiManager::GetSecurityType() const
{
    VerifyOrReturnValue(nullptr != mpWpaNetwork, EMBER_ZCL_SECURITY_TYPE_UNSPECIFIED);

    if ((mpWpaNetwork->key_mgmt & WPA_KEY_MGMT_NONE) || !wpa_key_mgmt_wpa_any(mpWpaNetwork->key_mgmt))
    {
        return EMBER_ZCL_SECURITY_TYPE_NONE;
    }
    else if (wpa_key_mgmt_wpa_psk_no_sae(mpWpaNetwork->key_mgmt))
    {
        return (mpWpaNetwork->pairwise_cipher & (WPA_CIPHER_TKIP | WPA_CIPHER_CCMP)) ? EMBER_ZCL_SECURITY_TYPE_WPA2
                                                                                     : EMBER_ZCL_SECURITY_TYPE_WPA3;
    }
    else if (wpa_key_mgmt_sae(mpWpaNetwork->key_mgmt))
    {
        return EMBER_ZCL_SECURITY_TYPE_WPA3;
    }
    else
    {
        return EMBER_ZCL_SECURITY_TYPE_WEP;
    }

    return EMBER_ZCL_SECURITY_TYPE_UNSPECIFIED;
}

uint8_t WiFiManager::FrequencyToChannel(uint16_t freq)
{
    static constexpr uint16_t k24MinFreq{ 2401 };
    static constexpr uint16_t k24MaxFreq{ 2484 };
    static constexpr uint8_t k24FreqConstDiff{ 5 };

    if (freq >= k24MinFreq && freq < k24MaxFreq)
    {
        return static_cast<uint8_t>((freq - k24MinFreq) / k24FreqConstDiff + 1);
    }
    else if (freq == k24MaxFreq)
    {
        return 14;
    }
    else if (freq > k24MaxFreq)
    {
        // assume we are in 5GH band
        return sFreqChannelMap[freq];
    }
    return 0;
}

CHIP_ERROR WiFiManager::GetNetworkStatistics(NetworkStatistics & stats) const
{
    // TODO: below will not work (result will be all zeros) until
    // the get_stats handler is implemented in WiFi driver
    net_stats_eth data{};
    net_mgmt(NET_REQUEST_STATS_GET_ETHERNET, InetUtils::GetInterface(), &data, sizeof(data));

    stats.mPacketMulticastRxCount = data.multicast.rx;
    stats.mPacketMulticastTxCount = data.multicast.tx;
    stats.mPacketUnicastRxCount   = data.pkts.rx - data.multicast.rx - data.broadcast.rx;
    stats.mPacketUnicastTxCount   = data.pkts.tx - data.multicast.tx - data.broadcast.tx;
    stats.mOverruns               = 0; // TODO: clarify if this can be queried from mgmt API (e.g. data.tx_dropped)

    return CHIP_NO_ERROR;
}

} // namespace DeviceLayer
} // namespace chip
