/*
 *
 *    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.
 */

#include <lib/support/CodeUtils.h>
#include <lib/support/SafeInt.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/mt793x/MT793XConfig.h>
#include <platform/mt793x/NetworkCommissioningWiFiDriver.h>

#include <limits>

using namespace ::chip;
using namespace ::chip::DeviceLayer::Internal;

namespace chip {
namespace DeviceLayer {
namespace NetworkCommissioning {

namespace {
NetworkCommissioning::WiFiScanResponse * sScanResult;
GenioScanResponseIterator<NetworkCommissioning::WiFiScanResponse> mScanResponseIter(sScanResult);
} // namespace

CHIP_ERROR GenioWiFiDriver::Init(NetworkStatusChangeCallback * networkStatusChangeCallback)
{
    CHIP_ERROR err;
    size_t ssidLen        = 0;
    size_t credentialsLen = 0;
    size_t outLen         = 0;
    mpScanCallback        = nullptr;
    mpConnectCallback     = nullptr;

    ChipLogProgress(NetworkProvisioning, "GenioWiFiDriver::Init");

    // If reading fails, wifi is not provisioned, no need to go further.
    err = MT793XConfig::ReadConfigValueStr(MT793XConfig::kConfigKey_WiFiSSID, mSavedNetwork.ssid, sizeof(mSavedNetwork.ssid),
                                           ssidLen);
    VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_NO_ERROR);

    err = MT793XConfig::ReadConfigValueStr(MT793XConfig::kConfigKey_WiFiPSK, mSavedNetwork.credentials,
                                           sizeof(mSavedNetwork.credentials), credentialsLen);
    VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_NO_ERROR);

    err = MT793XConfig::ReadConfigValueBin(MT793XConfig::kConfigKey_WiFiSEC, &mSavedNetwork.auth_mode,
                                           sizeof(mSavedNetwork.auth_mode), outLen);
    VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_NO_ERROR);

    mSavedNetwork.credentialsLen = credentialsLen;
    mSavedNetwork.ssidLen        = ssidLen;
    mStagingNetwork              = mSavedNetwork;

    ConnectWiFiNetwork(mSavedNetwork.ssid, ssidLen, mSavedNetwork.credentials, credentialsLen);
    return err;
}

CHIP_ERROR GenioWiFiDriver::CommitConfiguration()
{
    CHIP_ERROR err;

    ChipLogProgress(NetworkProvisioning, "GenioWiFiDriver::CommitConfiguration");

    ReturnErrorOnFailure(MT793XConfig::WriteConfigValueStr(MT793XConfig::kConfigKey_WiFiSSID, mStagingNetwork.ssid));

    ReturnErrorOnFailure(MT793XConfig::WriteConfigValueStr(MT793XConfig::kConfigKey_WiFiPSK, mStagingNetwork.credentials));

    ReturnErrorOnFailure(MT793XConfig::WriteConfigValueBin(MT793XConfig::kConfigKey_WiFiSEC, &mStagingNetwork.auth_mode,
                                                           sizeof(mStagingNetwork.auth_mode)));

    mSavedNetwork = mStagingNetwork;

    return CHIP_NO_ERROR;
}

CHIP_ERROR GenioWiFiDriver::RevertConfiguration()
{
    ChipLogProgress(NetworkProvisioning, "GenioWiFiDriver::RevertConfiguration");

    mStagingNetwork = mSavedNetwork;
    return CHIP_NO_ERROR;
}

bool GenioWiFiDriver::NetworkMatch(const WiFiNetwork & network, ByteSpan networkId)
{
    return networkId.size() == network.ssidLen && memcmp(networkId.data(), network.ssid, network.ssidLen) == 0;
}

Status GenioWiFiDriver::AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials, MutableCharSpan & outDebugText,
                                           uint8_t & outNetworkIndex)
{
    outDebugText.reduce_size(0);
    outNetworkIndex = 0;

    ChipLogProgress(NetworkProvisioning, "GenioWiFiDriver::AddOrUpdateNetwork");

    VerifyOrReturnError(mStagingNetwork.ssidLen == 0 || NetworkMatch(mStagingNetwork, ssid), Status::kBoundsExceeded);
    VerifyOrReturnError(credentials.size() <= sizeof(mStagingNetwork.credentials), Status::kOutOfRange);
    VerifyOrReturnError(ssid.size() <= sizeof(mStagingNetwork.ssid), Status::kOutOfRange);

    memset(mStagingNetwork.credentials, 0, sizeof(mStagingNetwork.credentials));
    memcpy(mStagingNetwork.credentials, credentials.data(), credentials.size());
    mStagingNetwork.credentialsLen = static_cast<decltype(mStagingNetwork.credentialsLen)>(credentials.size());

    memset(mStagingNetwork.ssid, 0, sizeof(mStagingNetwork.ssid));
    memcpy(mStagingNetwork.ssid, ssid.data(), ssid.size());
    mStagingNetwork.ssidLen = static_cast<decltype(mStagingNetwork.ssidLen)>(ssid.size());

    mStagingNetwork.auth_mode = WIFI_AUTH_MODE_WPA2_PSK;

    return Status::kSuccess;
}

Status GenioWiFiDriver::RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex)
{
    outDebugText.reduce_size(0);
    outNetworkIndex = 0;

    ChipLogProgress(NetworkProvisioning, "GenioWiFiDriver::RemoveNetwork");

    VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound);

    // Use empty ssid for representing invalid network
    mStagingNetwork.ssidLen = 0;
    return Status::kSuccess;
}

Status GenioWiFiDriver::ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText)
{
    ChipLogProgress(NetworkProvisioning, "GenioWiFiDriver::ReorderNetwork");

    outDebugText.reduce_size(0);
    // Only one network is supported for now
    VerifyOrReturnError(index == 0, Status::kOutOfRange);
    VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound);
    return Status::kSuccess;
}

CHIP_ERROR GenioWiFiDriver::ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, const char * key, uint8_t keyLen)
{
    ChipLogProgress(NetworkProvisioning, "GenioWiFiDriver::ConnectWiFiNetwork");

    ReturnErrorOnFailure(ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Enabled));

    // Set the wifi configuration
    filogic_wifi_sta_prov_t wifi_prov = {};
    memcpy(wifi_prov.ssid, ssid, ssidLen);
    memcpy(wifi_prov.psk, key, keyLen);
    wifi_prov.ssid_len  = ssidLen;
    wifi_prov.psk_len   = keyLen;
    wifi_prov.auth_mode = WIFI_AUTH_MODE_WPA2_PSK;

    ChipLogProgress(NetworkProvisioning, "Setting up connection for WiFi SSID: %.*s", static_cast<int>(ssidLen), ssid);

    void * filogicCtx = PlatformMgrImpl().mFilogicCtx;

    // Configure the FILOGIC WiFi interface.
    filogic_wifi_sta_prov_set_sync(filogicCtx, &wifi_prov);
    ReturnErrorOnFailure(ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Disabled));
    ReturnErrorOnFailure(ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Enabled));

    return CHIP_NO_ERROR;
}

void GenioWiFiDriver::OnConnectWiFiNetwork()
{
    ChipLogProgress(NetworkProvisioning, "GenioWiFiDriver::OnConnectWiFiNetwork");

    if (mpConnectCallback)
    {
        CommitConfiguration();
        mpConnectCallback->OnResult(Status::kSuccess, CharSpan(), 0);
        mpConnectCallback = nullptr;
    }
}

void GenioWiFiDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * callback)
{
    CHIP_ERROR err          = CHIP_NO_ERROR;
    Status networkingStatus = Status::kUnknownError;

    ChipLogProgress(NetworkProvisioning, "GenioWiFiDriver::ConnectNetwork");

    VerifyOrExit(NetworkMatch(mStagingNetwork, networkId), networkingStatus = Status::kNetworkIDNotFound);
    VerifyOrExit(mpConnectCallback == nullptr, networkingStatus = Status::kUnknownError);

    err = ConnectWiFiNetwork(mStagingNetwork.ssid, mStagingNetwork.ssidLen, mStagingNetwork.credentials,
                             mStagingNetwork.credentialsLen);
    if (err == CHIP_NO_ERROR)
    {
        mpConnectCallback = callback;
        networkingStatus  = Status::kSuccess;
    }

exit:
    if (networkingStatus != Status::kSuccess)
    {
        ChipLogError(NetworkProvisioning, "Failed to connect to WiFi network:%s", chip::ErrorStr(err));
        mpConnectCallback = nullptr;
        callback->OnResult(networkingStatus, CharSpan(), 0);
    }
}

chip::BitFlags<WiFiSecurity> GenioWiFiDriver::ConvertSecuritytype(wifi_auth_mode_t auth_mode)
{
    chip::BitFlags<WiFiSecurity> securityType;
    if (auth_mode == WIFI_AUTH_MODE_OPEN)
    {
        securityType = WiFiSecurity::kUnencrypted;
    }
    else if (auth_mode == WIFI_AUTH_MODE_WPA_PSK)
    {
        securityType = WiFiSecurity::kWpaPersonal;
    }
    else if (auth_mode == WIFI_AUTH_MODE_WPA2_PSK)
    {
        securityType = WiFiSecurity::kWpa2Personal;
    }
    else if (auth_mode == WIFI_AUTH_MODE_WPA3_PSK)
    {
        securityType = WiFiSecurity::kWpa3Personal;
    }
    else
    {
        securityType = WiFiSecurity::kUnencrypted;
    }

    return securityType;
}

bool GenioWiFiDriver::StartScanWiFiNetworks(ByteSpan ssid)
{
    ChipLogProgress(NetworkProvisioning, "GenioWiFiDriver::StartScanWiFiNetworks");

    ChipLogProgress(DeviceLayer, "Start Scan WiFi Networks");

    void * filogicCtx = PlatformMgrImpl().mFilogicCtx;

    if (!ssid.empty()) // ssid is given, only scan this network
    {
        char cSsid[DeviceLayer::Internal::kMaxWiFiSSIDLength] = {};
        memcpy(cSsid, ssid.data(), ssid.size());
        filogic_wifi_scan(filogicCtx, (uint8_t *) cSsid, ssid.size(), kMaxWiFiScanAPs, OnScanWiFiNetworkDone);
    }
    else // scan all networks
    {
        filogic_wifi_scan(filogicCtx, nullptr, 0, kMaxWiFiScanAPs, OnScanWiFiNetworkDone);
    }
    return true;
}

void GenioWiFiDriver::OnScanWiFiNetworkDone(wifi_scan_list_item_t * aScanResult)
{
    ChipLogProgress(NetworkProvisioning, "GenioWiFiDriver::OnScanWiFiNetworkDone");

    ChipLogProgress(DeviceLayer, "OnScanWiFiNetworkDone");
    if (!aScanResult)
    {
        if (GetInstance().mpScanCallback != nullptr)
        {
            DeviceLayer::SystemLayer().ScheduleLambda([]() {
                GetInstance().mpScanCallback->OnFinished(NetworkCommissioning::Status::kSuccess, CharSpan(), &mScanResponseIter);
                GetInstance().mpScanCallback = nullptr;
            });
        }
    }
    else
    {
        while (aScanResult->is_valid)
        {
            NetworkCommissioning::WiFiScanResponse scanResponse = {};
            chip::BitFlags<WiFiSecurity> security;

            security = GetInstance().ConvertSecuritytype(aScanResult->auth_mode);

            scanResponse.security.Set(security);
            scanResponse.channel = aScanResult->channel;
            scanResponse.rssi    = aScanResult->rssi;
            scanResponse.ssidLen = strnlen((char *) aScanResult->ssid, DeviceLayer::Internal::kMaxWiFiSSIDLength);
            memcpy(scanResponse.ssid, aScanResult->ssid, scanResponse.ssidLen);
            memcpy(scanResponse.bssid, aScanResult->bssid, sizeof(scanResponse.bssid));

            mScanResponseIter.Add(&scanResponse);

            aScanResult++; // process next result
        }
    }
}

void GenioWiFiDriver::ScanNetworks(ByteSpan ssid, WiFiDriver::ScanCallback * callback)
{
    ChipLogProgress(NetworkProvisioning, "GenioWiFiDriver::ScanNetworks");

    if (callback != nullptr)
    {
        mpScanCallback = callback;
        if (!StartScanWiFiNetworks(ssid))
        {
            ChipLogError(DeviceLayer, "ScanWiFiNetworks failed to start");
            mpScanCallback = nullptr;
            callback->OnFinished(Status::kUnknownError, CharSpan(), nullptr);
        }
    }
}

CHIP_ERROR GetConnectedNetwork(Network & network)
{
    ChipLogProgress(NetworkProvisioning, "GetConnectedNetwork");

    void * filogicCtx = PlatformMgrImpl().mFilogicCtx;

    filogic_wifi_sta_prov_t wifi_prov;

    if (!filogic_wifi_sta_get_link_status_sync(filogicCtx) || !filogic_wifi_sta_prov_get_sync(filogicCtx, &wifi_prov))
    {
        return CHIP_ERROR_INCORRECT_STATE;
    }

    uint8_t length = strnlen(wifi_prov.ssid, DeviceLayer::Internal::kMaxWiFiSSIDLength);
    if (length > sizeof(network.networkID))
    {
        ChipLogError(DeviceLayer, "SSID too long");
        return CHIP_ERROR_INTERNAL;
    }

    memcpy(network.networkID, wifi_prov.ssid, length);
    network.networkIDLen = length;

    return CHIP_NO_ERROR;
}

size_t GenioWiFiDriver::WiFiNetworkIterator::Count()
{
    ChipLogProgress(NetworkProvisioning, "GenioWiFiDriver::WiFiNetworkIterator::Count");

    return mDriver->mStagingNetwork.ssidLen == 0 ? 0 : 1;
}

bool GenioWiFiDriver::WiFiNetworkIterator::Next(Network & item)
{
    ChipLogProgress(NetworkProvisioning, "GenioWiFiDriver::WiFiNetworkIterator::Next");

    if (mExhausted || mDriver->mStagingNetwork.ssidLen == 0)
    {
        return false;
    }
    memcpy(item.networkID, mDriver->mStagingNetwork.ssid, mDriver->mStagingNetwork.ssidLen);
    item.networkIDLen = mDriver->mStagingNetwork.ssidLen;
    item.connected    = false;
    mExhausted        = true;

    Network connectedNetwork;
    CHIP_ERROR err = GetConnectedNetwork(connectedNetwork);
    if (err == CHIP_NO_ERROR)
    {
        if (connectedNetwork.networkIDLen == item.networkIDLen &&
            memcmp(connectedNetwork.networkID, item.networkID, item.networkIDLen) == 0)
        {
            item.connected = true;
        }
    }
    return true;
}

} // namespace NetworkCommissioning
} // namespace DeviceLayer
} // namespace chip
