/*
 *
 *    Copyright (c) 2022 Project CHIP Authors
 *    All rights reserved.
 *
 *    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/CommissionableDataProvider.h>
#include <platform/ConnectivityManager.h>

#include "ConnectivityManagerImplWiFi.h"
#include "WiFiManager.h"

#if CHIP_DEVICE_CONFIG_ENABLE_WIFI

using namespace ::chip;
using namespace ::chip::Inet;
using namespace ::chip::System;
using namespace ::chip::TLV;

namespace chip {
namespace DeviceLayer {

CHIP_ERROR ConnectivityManagerImplWiFi::InitWiFi()
{
    return WiFiManager::Instance().Init();
}

ConnectivityManager::WiFiStationMode ConnectivityManagerImplWiFi::_GetWiFiStationMode(void)
{
    if (mStationMode != ConnectivityManager::WiFiStationMode::kWiFiStationMode_ApplicationControlled)
    {
        mStationMode = (WiFiManager::StationStatus::DISABLED == WiFiManager().Instance().GetStationStatus())
            ? ConnectivityManager::WiFiStationMode::kWiFiStationMode_Disabled
            : ConnectivityManager::WiFiStationMode::kWiFiStationMode_Enabled;
    }
    return mStationMode;
}

CHIP_ERROR ConnectivityManagerImplWiFi::_SetWiFiStationMode(ConnectivityManager::WiFiStationMode aMode)
{
    VerifyOrReturnError(ConnectivityManager::WiFiStationMode::kWiFiStationMode_NotSupported != aMode, CHIP_ERROR_INVALID_ARGUMENT);

    mStationMode = aMode;

    return CHIP_NO_ERROR;
}

bool ConnectivityManagerImplWiFi::_IsWiFiStationEnabled(void)
{
    return (WiFiManager::StationStatus::DISABLED <= WiFiManager().Instance().GetStationStatus());
}

bool ConnectivityManagerImplWiFi::_IsWiFiStationApplicationControlled(void)
{
    return (ConnectivityManager::WiFiStationMode::kWiFiStationMode_ApplicationControlled == mStationMode);
}

bool ConnectivityManagerImplWiFi::_IsWiFiStationConnected(void)
{
    return (WiFiManager::StationStatus::CONNECTED == WiFiManager().Instance().GetStationStatus());
}

System::Clock::Timeout ConnectivityManagerImplWiFi::_GetWiFiStationReconnectInterval(void)
{
    return mWiFiStationReconnectInterval;
}

CHIP_ERROR ConnectivityManagerImplWiFi::_SetWiFiStationReconnectInterval(System::Clock::Timeout val)
{
    mWiFiStationReconnectInterval = val;
    return CHIP_NO_ERROR;
}

bool ConnectivityManagerImplWiFi::_IsWiFiStationProvisioned(void)
{
    // from Matter perspective `provisioned` means that the supplicant has been provided
    // with SSID and password (doesn't matter if valid or not)
    return (WiFiManager::StationStatus::CONNECTING <= WiFiManager().Instance().GetStationStatus());
}

void ConnectivityManagerImplWiFi::_ClearWiFiStationProvision(void)
{
    if (_IsWiFiStationProvisioned())
    {
        if (CHIP_NO_ERROR != WiFiManager().Instance().ClearStationProvisioningData())
        {
            ChipLogError(DeviceLayer, "Cannot clear WiFi station provisioning data");
        }
    }
}

bool ConnectivityManagerImplWiFi::_CanStartWiFiScan()
{
    return (WiFiManager::StationStatus::DISABLED != WiFiManager().Instance().GetStationStatus() &&
            WiFiManager::StationStatus::SCANNING != WiFiManager().Instance().GetStationStatus() &&
            WiFiManager::StationStatus::CONNECTING != WiFiManager().Instance().GetStationStatus());
}

void ConnectivityManagerImplWiFi::_OnWiFiStationProvisionChange()
{
    // do nothing
}

void ConnectivityManagerImplWiFi::_OnWiFiScanDone() {}

CHIP_ERROR ConnectivityManagerImplWiFi::_GetAndLogWiFiStatsCounters(void)
{
    // TODO: when network statistics are enabled
    return CHIP_NO_ERROR;
}

#if CHIP_DEVICE_CONFIG_ENABLE_SED
CHIP_ERROR ConnectivityManagerImplWiFi::_GetSEDIntervalsConfig(ConnectivityManager::SEDIntervalsConfig & SEDIntervalsConfig)
{
    // For now Wi-Fi uses legacy power save mode that has fixed inactivity interval
    SEDIntervalsConfig.ActiveIntervalMS =
        chip::System::Clock::Milliseconds32(WiFiManager::kDefaultDTIMInterval * WiFiManager::kBeaconIntervalMs);
    SEDIntervalsConfig.IdleIntervalMS =
        chip::System::Clock::Milliseconds32(WiFiManager::kDefaultDTIMInterval * WiFiManager::kBeaconIntervalMs);
    return CHIP_NO_ERROR;
}
CHIP_ERROR ConnectivityManagerImplWiFi::_SetSEDIntervalsConfig(const ConnectivityManager::SEDIntervalsConfig & intervalsConfig)
{
    return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
}
CHIP_ERROR ConnectivityManagerImplWiFi::_RequestSEDActiveMode(bool onOff, bool delayIdle)
{
    return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
}
#endif

ConnectivityManager::WiFiAPMode ConnectivityManagerImplWiFi::_GetWiFiAPMode(void)
{
    /* AP mode is unsupported */
    return ConnectivityManager::WiFiAPMode::kWiFiAPMode_NotSupported;
}

CHIP_ERROR ConnectivityManagerImplWiFi::_SetWiFiAPMode(ConnectivityManager::WiFiAPMode mode)
{
    /* AP mode is unsupported */
    VerifyOrReturnError(ConnectivityManager::WiFiAPMode::kWiFiAPMode_NotSupported == mode ||
                            ConnectivityManager::WiFiAPMode::kWiFiAPMode_Disabled == mode,
                        CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
    return CHIP_NO_ERROR;
}

bool ConnectivityManagerImplWiFi::_IsWiFiAPActive(void)
{
    /* AP mode is unsupported */
    return false;
}

bool ConnectivityManagerImplWiFi::_IsWiFiAPApplicationControlled(void)
{
    /* AP mode is unsupported */
    return false;
}

void ConnectivityManagerImplWiFi::_DemandStartWiFiAP(void)
{ /* AP mode is unsupported */
}

void ConnectivityManagerImplWiFi::_StopOnDemandWiFiAP(void)
{ /* AP mode is unsupported */
}

void ConnectivityManagerImplWiFi::_MaintainOnDemandWiFiAP(void)
{ /* AP mode is unsupported */
}

System::Clock::Timeout ConnectivityManagerImplWiFi::_GetWiFiAPIdleTimeout(void)
{
    /* AP mode is unsupported */
    return System::Clock::kZero;
}

void ConnectivityManagerImplWiFi::_SetWiFiAPIdleTimeout(System::Clock::Timeout val)
{ /* AP mode is unsupported */
}

} // namespace DeviceLayer
} // namespace chip

#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI
