/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    Copyright (c) 2019 Nest Labs, Inc.
 *
 *    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.
 */
/* this file behaves like a config.h, comes first */
#include <platform/internal/CHIPDeviceLayerInternal.h>

#include <platform/ConnectivityManager.h>

#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/ConnectivityManager.h>
#include <platform/internal/BLEManager.h>
#include <platform/mt793x/NetworkCommissioningWiFiDriver.h>

#include <lwip/dns.h>
#include <lwip/ip_addr.h>
#include <lwip/nd6.h>
#include <lwip/netif.h>

#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
#include <platform/internal/GenericConnectivityManagerImpl_BLE.ipp>
#endif

#include "mt7933_pos.h"
#include "wifi_api_ex.h"

using namespace ::chip;
using namespace ::chip::Inet;
using namespace ::chip::System;
using namespace ::chip::DeviceLayer::Internal;

namespace chip {
namespace DeviceLayer {

CHIP_ERROR ConnectivityManagerImpl::WiFiInit(void)
{
    CHIP_ERROR err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;

    ChipLogProgress(DeviceLayer, "ConnectivityManager Wi-Fi init");

#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
    // Queue work items to bootstrap the AP and station state machines once
    // the Chip event loop is running.
    mWiFiStationMode              = kWiFiStationMode_Disabled;
    mWiFiStationState             = kWiFiStationState_NotConnected;
    mLastStationConnectFailTime   = System::Clock::kZero;
    mWiFiStationReconnectInterval = System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_WIFI_STATION_RECONNECT_INTERVAL);
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP
    mWiFiAPMode        = kWiFiAPMode_Disabled;
    mWiFiAPState       = kWiFiAPState_NotActive;
    mWiFiAPIdleTimeout = System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_WIFI_AP_IDLE_TIMEOUT);
    mLastAPDemandTime  = System::Clock::kZero;
#endif
    mFlags.ClearAll();

    mFilogicCtx = PlatformMgrImpl().mFilogicCtx;

    if (!IsWiFiStationProvisioned())
    {
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP
        mWiFiAPMode  = kWiFiAPMode_Enabled;
        mWiFiAPState = kWiFiAPState_NotActive;
        filogic_wifi_init_async(mFilogicCtx, FILOGIC_WIFI_OPMODE_AP);
        err = CHIP_NO_ERROR;
        SuccessOrExit(err);
#endif
    }
    else
    {
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
        mWiFiStationMode  = kWiFiStationMode_Enabled;
        mWiFiStationState = kWiFiStationState_NotConnected;
        filogic_wifi_init_async(mFilogicCtx, FILOGIC_WIFI_OPMODE_STA);
        err = CHIP_NO_ERROR;
        SuccessOrExit(err);
#endif
    }

    ChipLogProgress(DeviceLayer, "ConnectivityManager Wi-Fi init done");

exit:
    return err;
}

void ConnectivityManagerImpl::ChangeWiFiAPState(WiFiAPState newState)
{
    if (mWiFiAPState != newState)
    {
        ChipLogProgress(DeviceLayer, "WiFi AP state change: %s -> %s", WiFiAPStateToStr(mWiFiAPState), WiFiAPStateToStr(newState));
        mWiFiAPState = newState;
    }
}

void ConnectivityManagerImpl::_OnWiFiPlatformEvent(const ChipDeviceEvent * event)
{
    if (event->Type != DeviceEventType::kMtkWiFiEvent)
        return;

    ChipLogProgress(DeviceLayer, "%s WiFi event %s", __func__, filogic_event_to_name(event->Platform.FilogicEvent.event));

    const filogic_async_event_data * event_data;
    bool hadIPv4Conn = mFlags.Has(ConnectivityFlags::kHaveIPv4InternetConnectivity);
    bool hadIPv6Conn = mFlags.Has(ConnectivityFlags::kHaveIPv6InternetConnectivity);

    event_data = &event->Platform.MtkWiFiEvent.event_data;

    if (event_data->event_id == FILOGIC_WIFI_INIT_OK)
    {
        if (FILOGIC_WIFI_PORT_STA == event_data->u.wifi_init.port)
        {
            mWiFiStationState = kWiFiStationState_NotConnected;
            DriveStationState();
        }
        else if (FILOGIC_WIFI_PORT_AP == event_data->u.wifi_init.port)
        {
            ConfigureWiFiAP();
            ChangeWiFiAPState(kWiFiAPState_Activating);
        }
        else
            assert(0);
    }
    else if (event_data->event_id == FILOGIC_AP_START_OK)
    {
        ChangeWiFiAPState(kWiFiAPState_Active);
    }
    else if (event_data->event_id == FILOGIC_SET_OPMODE_OK)
    {
        if (event_data->u.wifi_opmode.opmode == WIFI_MODE_STA_ONLY)
            ChangeWiFiStationState(kWiFiStationState_NotConnected);
        else if (event_data->u.wifi_opmode.opmode == WIFI_MODE_AP_ONLY)
            ChangeWiFiAPState(kWiFiAPState_Active);
        else
            assert(0);
    }
    else if (event_data->event_id == FILOGIC_AP_STATION_CONNECTED)
    {
        MaintainOnDemandWiFiAP();
    }
    else if (event_data->event_id == FILOGIC_AP_STATION_DISCONNECTED)
    {
    }
    else if (event_data->event_id == FILOGIC_STA_DISCONNECTED_FROM_AP)
    {
        if (mWiFiStationState == kWiFiStationState_Connecting)
        {
            ChangeWiFiStationState(kWiFiStationState_Connecting_Failed);
        }
        DriveStationState();
    }
    else if (!hadIPv4Conn && event_data->event_id == FILOGIC_STA_IPV4_ADDR_READY)
    {
        if (mWiFiStationState == kWiFiStationState_Connecting)
        {
            ChangeWiFiStationState(kWiFiStationState_Connecting_Succeeded);
        }

        ChipLogProgress(DeviceLayer, "ip addr: %s", event_data->u.ipv4_str.addr);
        DriveStationState();
        UpdateInternetConnectivityState(TRUE, hadIPv6Conn, event_data->u.ipv4_str.addr);
    }

    if (!hadIPv6Conn && event_data->event_id == FILOGIC_STA_IPV6_ADDR_READY)
    {
        if (mWiFiStationState == kWiFiStationState_Connecting)
        {
            ChangeWiFiStationState(kWiFiStationState_Connecting_Succeeded);
        }

        const char * addrv6 = (const char *) &event_data->u.ipv6_str.addr[0];
        ChipLogProgress(DeviceLayer, "ip addr: %s", addrv6);

        DriveStationState();

        UpdateInternetConnectivityState(hadIPv4Conn, TRUE, event_data->u.ipv6_str.addr);
    }
    else if (event->Platform.FilogicEvent.event == FILOGIC_STA_CONNECTED_TO_AP)
    {
        ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_CONNECTED");
        if (mWiFiStationState == kWiFiStationState_Connecting)
        {
            ChangeWiFiStationState(kWiFiStationState_Connecting_Succeeded);
        }
        DriveStationState();
    }
}

#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
ConnectivityManager::WiFiStationMode ConnectivityManagerImpl::GetFilogicStationMode(void)
{
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
    filogic_wifi_opmode_t opmode;
    int32_t ret;

    filogic_wifi_opmode_get_sync(mFilogicCtx, &opmode);

    if (opmode == FILOGIC_WIFI_OPMODE_STA || opmode == FILOGIC_WIFI_OPMODE_DUAL)
        return kWiFiStationMode_Enabled;
#endif
    return kWiFiStationMode_Disabled;
}

ConnectivityManager::WiFiAPMode ConnectivityManagerImpl::GetFilogicAPMode(void)
{
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP
    filogic_wifi_opmode_t opmode;
    int32_t ret;

    filogic_wifi_opmode_get_sync(mFilogicCtx, &opmode);

    if (opmode == FILOGIC_WIFI_OPMODE_AP || opmode == FILOGIC_WIFI_OPMODE_DUAL)
        return kWiFiAPMode_Enabled;
#endif
    return kWiFiAPMode_Disabled;
}

filogic_wifi_opmode_t ConnectivityManagerImpl::GetFilogicNextOpMode(WiFiStationMode staMode, WiFiAPMode apMode)
{
    bool sta, ap;
    filogic_wifi_opmode_t opmode;

    ChipLogProgress(DeviceLayer, "%s %d %d", __func__, staMode, apMode);

    sta = staMode == kWiFiStationMode_Enabled;
    ap  = apMode == kWiFiAPMode_Enabled;

    if (sta && ap)
        opmode = FILOGIC_WIFI_OPMODE_DUAL;
    else if (ap)
        opmode = FILOGIC_WIFI_OPMODE_AP;
    else if (sta)
        opmode = FILOGIC_WIFI_OPMODE_STA;
    else
        opmode = FILOGIC_WIFI_OPMODE_NONE;

    return opmode;
}

void ConnectivityManagerImpl::SetFlogicNextMode(filogic_wifi_opmode_t nextMode)
{
    ChipLogProgress(DeviceLayer, "WiFi driver mode set %s", filogic_opmode_to_name(nextMode));
    filogic_wifi_opmode_set_async(mFilogicCtx, nextMode);
}
#endif

#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
ConnectivityManager::WiFiStationMode ConnectivityManagerImpl::_GetWiFiStationMode(void)
{
    if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled)
    {
        filogic_wifi_opmode_t opmode;

        filogic_wifi_opmode_get_sync(mFilogicCtx, &opmode);

        if (opmode == FILOGIC_WIFI_OPMODE_AP)
            mWiFiStationMode = kWiFiStationMode_Disabled;
        else
            mWiFiStationMode = kWiFiStationMode_Enabled;
    }
    return mWiFiStationMode;
}

CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationMode(ConnectivityManager::WiFiStationMode val)
{
    ChipLogProgress(DeviceLayer, "%s", __func__);

    if (mWiFiStationMode != val)
    {
        ChipLogProgress(DeviceLayer, "WiFi station mode change: %s -> %s", WiFiStationModeToStr(mWiFiStationMode),
                        WiFiStationModeToStr(val));
        DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL);
        mWiFiStationMode = val;
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationReconnectInterval(System::Clock::Timeout val)
{
    ChipLogProgress(DeviceLayer, "%s", __func__);

    mWiFiStationReconnectInterval = val;
    return CHIP_NO_ERROR;
}

CHIP_ERROR ConnectivityManagerImpl::_GetAndLogWifiStatsCounters(void)
{
    ChipLogProgress(DeviceLayer, "%s", __func__);

    return CHIP_ERROR_NOT_IMPLEMENTED;
}

bool ConnectivityManagerImpl::_IsWiFiStationEnabled(void)
{
    return GetWiFiStationMode() == kWiFiStationMode_Enabled;
}

bool ConnectivityManagerImpl::_IsWiFiStationProvisioned(void)
{
    filogic_wifi_sta_prov_t prov = {};

    /* See if we have SSID */
    if (filogic_wifi_sta_prov_get_sync(mFilogicCtx, &prov))
    {
        return prov.ssid[0] != '\0';
    }

    return false;
}

void ConnectivityManagerImpl::_ClearWiFiStationProvision(void)
{
    ChipLogProgress(DeviceLayer, "%s", __func__);

    if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled)
    {
#ifdef MT793X_PORTING
        wfx_clear_wifi_provision();
#endif /* MT793X_PORTING */

        DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL);
    }
}

void ConnectivityManagerImpl::_OnWiFiScanDone()
{
    // CHIP_ERROR_NOT_IMPLEMENTED
}

void ConnectivityManagerImpl::_OnWiFiStationProvisionChange()
{
    ChipLogProgress(DeviceLayer, "%s", __func__);

    // Schedule a call to the DriveStationState method to adjust the station state as needed.
    ChipLogProgress(DeviceLayer, "_ON WIFI PROVISION CHANGE");
    DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL);
}
#endif

#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP
void ConnectivityManagerImpl::DriveAPState(void)
{
    CHIP_ERROR err          = CHIP_NO_ERROR;
    WiFiAPMode driverAPMode = GetFilogicAPMode();
    filogic_wifi_opmode_t nextMode;

    ChipLogProgress(DeviceLayer, "%s", __func__);

    if (mWiFiAPMode != driverAPMode)
    {
        nextMode = GetFilogicNextOpMode(mWiFiStationMode, driverAPMode);
        ChipLogProgress(DeviceLayer, "WiFi Driver AP mode set: %d", nextMode);
        SetFlogicNextMode(nextMode);
        if (driverAPMode == kWiFiAPMode_Enabled)
        {
        }
        // TODO wait driver event
    }
}

CHIP_ERROR ConnectivityManagerImpl::ConfigureWiFiAP(void)
{
    char ssid[32];
    int ssid_len;

    ChipLogProgress(DeviceLayer, "%s", __func__);

    CHIP_ERROR err = CHIP_NO_ERROR;

    // TODO, generate
    uint16_t discriminator = 0x8888;

    ssid_len       = snprintf(ssid, sizeof(ssid), "%s%03X-%04X-%04X", CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX, discriminator,
                              CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID, CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID);
    int8_t channel = CHIP_DEVICE_CONFIG_WIFI_AP_CHANNEL;

    filogic_wifi_ap_config_async(mFilogicCtx, channel, ssid, ssid_len);

    return err;
}

void ConnectivityManagerImpl::DriveAPState(::chip::System::Layer * aLayer, void * aAppState)
{
    sInstance.DriveAPState();
}

CHIP_ERROR ConnectivityManagerImpl::_SetWiFiAPMode(WiFiAPMode val)
{
    ChipLogProgress(DeviceLayer, "%s", __func__);

    CHIP_ERROR err = CHIP_NO_ERROR;

    VerifyOrExit(val != kWiFiAPMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);

    if (mWiFiAPMode != val)
    {
        ChipLogProgress(DeviceLayer, "WiFi AP mode change: %s -> %s", WiFiAPModeToStr(mWiFiAPMode), WiFiAPModeToStr(val));
    }

    mWiFiAPMode = val;

exit:
    return err;
}

void ConnectivityManagerImpl::_DemandStartWiFiAP(void)
{
    ChipLogProgress(DeviceLayer, "%s", __func__);

    if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision)
    {
        mLastAPDemandTime = System::SystemClock().GetMonotonicTimestamp();
        DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL);
    }
}

void ConnectivityManagerImpl::_StopOnDemandWiFiAP(void)
{
    ChipLogProgress(DeviceLayer, "%s", __func__);

    if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision)
    {
        mLastAPDemandTime = System::Clock::kZero;
        DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL);
    }
}

void ConnectivityManagerImpl::_MaintainOnDemandWiFiAP(void)
{
    ChipLogProgress(DeviceLayer, "%s", __func__);

    if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision)
    {
        if (mWiFiAPState == kWiFiAPState_Activating || mWiFiAPState == kWiFiAPState_Active)
        {
            mLastAPDemandTime = System::SystemClock().GetMonotonicTimestamp();
        }
    }
}

void ConnectivityManagerImpl::_SetWiFiAPIdleTimeout(System::Clock::Timeout val)
{
    ChipLogProgress(DeviceLayer, "%s", __func__);

    mWiFiAPIdleTimeout = val;
    DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL);
}
#endif /* CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP */

/****************************************************************************
 * ConnectivityManager Private Methods
 ****************************************************************************/

#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
void ConnectivityManagerImpl::DriveStationState()
{
    ChipLogProgress(DeviceLayer, "%s", __func__);

    CHIP_ERROR err = CHIP_NO_ERROR;
    int32_t status;
    bool stationConnected;

    // Refresh the current station mode.
    GetWiFiStationMode();

    // If the station interface is NOT under application control...
    if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled)
    {
        if (mWiFiStationMode != kWiFiStationMode_Enabled)
        {
            ChipLogProgress(DeviceLayer, "WiFi station mode set");
            mWiFiStationState = kWiFiStationState_NotConnected;
            SetFlogicNextMode(FILOGIC_WIFI_OPMODE_STA);
            return;
        }
    }

    stationConnected = filogic_wifi_sta_get_link_status_sync(mFilogicCtx);

    // If the station interface is currently connected ...
    if (stationConnected)
    {
        // Advance the station state to Connected if it was previously NotConnected or
        // a previously initiated connect attempt succeeded.
        if (mWiFiStationState == kWiFiStationState_NotConnected || mWiFiStationState == kWiFiStationState_Connecting_Succeeded)
        {
            ChangeWiFiStationState(kWiFiStationState_Connected);
            ChipLogProgress(DeviceLayer, "WiFi station interface connected");
            mLastStationConnectFailTime = System::Clock::kZero;
            OnStationConnected();
        }

        // If the WiFi station interface is no longer enabled, or no longer provisioned,
        // disconnect the station from the AP, unless the WiFi station mode is currently
        // under application control.
        if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled &&
            (mWiFiStationMode != kWiFiStationMode_Enabled || !IsWiFiStationProvisioned()))
        {
            ChipLogProgress(DeviceLayer, "Disconnecting WiFi station interface");

            status = wifi_connection_disconnect_ap();
            if (status < 0)
            {
                ChipLogError(DeviceLayer, "WiFi disconnect : FAIL: %ld", status);
            }

            ChangeWiFiStationState(kWiFiStationState_Disconnecting);
        }
    }
    // Otherwise the station interface is NOT connected to an AP, so...
    else
    {
        System::Clock::Timestamp now = System::SystemClock().GetMonotonicTimestamp();

        // Advance the station state to NotConnected if it was previously Connected or Disconnecting,
        // or if a previous initiated connect attempt failed.
        if (mWiFiStationState == kWiFiStationState_Connected || mWiFiStationState == kWiFiStationState_Disconnecting ||
            mWiFiStationState == kWiFiStationState_Connecting_Failed)
        {
            WiFiStationState prevState = mWiFiStationState;
            ChangeWiFiStationState(kWiFiStationState_NotConnected);
            if (prevState != kWiFiStationState_Connecting_Failed)
            {
                ChipLogProgress(DeviceLayer, "WiFi station interface disconnected");
                mLastStationConnectFailTime = System::Clock::kZero;
                OnStationDisconnected();
            }
            else
            {
                mLastStationConnectFailTime = now;
            }
        }

        // If the WiFi station interface is now enabled and provisioned (and by implication,
        // not presently under application control), AND the system is not in the process of
        // scanning, then...
        if (mWiFiStationMode == kWiFiStationMode_Enabled && IsWiFiStationProvisioned())
        {
            // Initiate a connection to the AP if we haven't done so before, or if enough
            // time has passed since the last attempt.
            if (mLastStationConnectFailTime == System::Clock::kZero ||
                now >= mLastStationConnectFailTime + mWiFiStationReconnectInterval)
            {
                if (mWiFiStationState != kWiFiStationState_Connecting)
                {
                    ChipLogProgress(DeviceLayer, "Attempting to connect WiFi");

                    status = wifi_config_reload_setting();

                    if (status < 0)
                    {
                        ChipLogError(DeviceLayer, "WiFi start connect : FAIL %ld", status);
                        goto exit;
                    }

                    ChangeWiFiStationState(kWiFiStationState_Connecting);
                }
            }
            // Otherwise arrange another connection attempt at a suitable point in the future.
            else
            {
                System::Clock::Timestamp timeToNextConnect = (mLastStationConnectFailTime + mWiFiStationReconnectInterval) - now;

                ChipLogProgress(DeviceLayer, "Next WiFi station reconnect in %" PRIu32 " ms",
                                System::Clock::Milliseconds32(timeToNextConnect).count());

                ReturnOnFailure(DeviceLayer::SystemLayer().StartTimer(timeToNextConnect, DriveStationState, NULL));
            }
        }
    }

exit:

    ChipLogProgress(DeviceLayer, "Done driving station state, nothing else to do...");
}

void ConnectivityManagerImpl::OnStationConnected()
{
    ChipLogProgress(DeviceLayer, "%s", __func__);

    ChipDeviceEvent event;

    NetworkCommissioning::GenioWiFiDriver::GetInstance().OnConnectWiFiNetwork();

    // Alert other components of the new state.
    event.Type                          = DeviceEventType::kWiFiConnectivityChange;
    event.WiFiConnectivityChange.Result = kConnectivity_Established;
    (void) PlatformMgr().PostEvent(&event);

    UpdateInternetConnectivityState(FALSE, FALSE, NULL);
}

void ConnectivityManagerImpl::OnStationDisconnected()
{
    ChipLogProgress(DeviceLayer, "%s", __func__);

    // TODO Invoke WARM to perform actions that occur when the WiFi station interface goes down.

    // Alert other components of the new state.
    ChipDeviceEvent event;
    event.Type                          = DeviceEventType::kWiFiConnectivityChange;
    event.WiFiConnectivityChange.Result = kConnectivity_Lost;
    (void) PlatformMgr().PostEvent(&event);

    UpdateInternetConnectivityState(FALSE, FALSE, NULL);
}

void ConnectivityManagerImpl::DriveStationState(::chip::System::Layer * aLayer, void * aAppState)
{
    ChipLogProgress(DeviceLayer, "%s", __func__);

    sInstance.DriveStationState();
}

void ConnectivityManagerImpl::ChangeWiFiStationState(WiFiStationState newState)
{
    ChipLogProgress(DeviceLayer, "%s", __func__);

    if (mWiFiStationState != newState)
    {
        ChipLogProgress(DeviceLayer, "WiFi station state change: %s -> %s", WiFiStationStateToStr(mWiFiStationState),
                        WiFiStationStateToStr(newState));
        mWiFiStationState = newState;
    }
}

void ConnectivityManagerImpl::UpdateInternetConnectivityState(bool haveIPv4Conn, bool haveIPv6Conn, const uint8_t * ipAddr)
{
    ChipLogProgress(DeviceLayer, "%s", __func__);

    bool hadIPv4Conn = mFlags.Has(ConnectivityFlags::kHaveIPv4InternetConnectivity);
    bool hadIPv6Conn = mFlags.Has(ConnectivityFlags::kHaveIPv6InternetConnectivity);

    ConnectivityChange connV4Change = GetConnectivityChange(hadIPv4Conn, haveIPv4Conn);
    ConnectivityChange connV6Change = GetConnectivityChange(hadIPv6Conn, haveIPv6Conn);

    IPAddress addr;

    // If the WiFi station is currently in the connected state...
    if (mWiFiStationState == kWiFiStationState_Connected)
    {
        IPAddress::FromString((char *) ipAddr, addr);
    }

    // If the internet connectivity state has changed...
    if (connV4Change != kConnectivity_NoChange)
    {
        // Update the current state.
        mFlags.Set(ConnectivityFlags::kHaveIPv4InternetConnectivity, haveIPv4Conn);

        // Alert other components of the state change.
        ChipDeviceEvent event;
        event.Type                                 = DeviceEventType::kInternetConnectivityChange;
        event.InternetConnectivityChange.IPv4      = connV4Change;
        event.InternetConnectivityChange.IPv6      = kConnectivity_NoChange;
        event.InternetConnectivityChange.ipAddress = addr;

        (void) PlatformMgr().PostEvent(&event);

        ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv4", (haveIPv4Conn) ? "ESTABLISHED" : "LOST");
    }

    // If the internet connectivity state has changed...
    if (connV6Change != kConnectivity_NoChange)
    {
        // Update the current state.
        mFlags.Set(ConnectivityFlags::kHaveIPv6InternetConnectivity, haveIPv6Conn);

        // Alert other components of the state change.
        ChipDeviceEvent event;
        event.Type                                 = DeviceEventType::kInternetConnectivityChange;
        event.InternetConnectivityChange.IPv4      = kConnectivity_NoChange;
        event.InternetConnectivityChange.IPv6      = connV6Change;
        event.InternetConnectivityChange.ipAddress = addr;

        (void) PlatformMgr().PostEvent(&event);

        ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv6", (haveIPv6Conn) ? "ESTABLISHED" : "LOST");
    }
}
#endif

} // namespace DeviceLayer
} // namespace chip
