/*
 *
 *    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/BytesToHex.h>
#include <lib/support/CodeUtils.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/Darwin/ConfigurationManagerImpl.h>
#include <platform/Darwin/WiFi/NetworkCommissioningWiFiDriver.h>

#import <CoreFoundation/CoreFoundation.h>
#import <CoreWLAN/CoreWLAN.h>

using namespace chip;
using namespace chip::DeviceLayer;
using namespace chip::DeviceLayer::NetworkCommissioning;
using chip::DeviceLayer::ConfigurationManagerImpl;

constexpr size_t kMaxNetworks = 1;
constexpr size_t kScanNetworkTimeoutSeconds = 30;
constexpr size_t kConnectNetworkTimeoutSeconds = 30;

namespace {
class DarwinWiFiNetworkIterator final : public DarwinNetworkIterator {
public:
    DarwinWiFiNetworkIterator()
    {
        auto & connectivityMgr = ConnectivityMgrImpl();
        ReturnOnFailure(connectivityMgr.GetWiFiInterfaceName(mInterfaceName, sizeof(mInterfaceName)));
        ReturnOnFailure(connectivityMgr.GetInterfaceStatus(mInterfaceName, &mInterfaceStatus));
        mInterfaceCount++;
    }
};

class DarwinScanResponseIterator : public Iterator<WiFiScanResponse> {
public:
    DarwinScanResponseIterator(NSArray * networks) { mNetworks = networks; }

    bool Next(WiFiScanResponse & scanResponse) override
    {
        if (mIndex >= [mNetworks count]) {
            return false;
        }

        CWNetwork * network = mNetworks[mIndex];
        CopyNetworkInformationTo(scanResponse, network);

        mIndex++;
        return true;
    }

    size_t Count() override { return [mNetworks count]; }

    void Release() override { mNetworks = nil; }

private:
    NSArray * mNetworks = nil;
    size_t mIndex = 0;

    void CopyNetworkInformationTo(WiFiScanResponse & destination, CWNetwork * source)
    {
        destination.security = GetWiFiSecurity(source);
        destination.channel = static_cast<uint16_t>(source.wlanChannel.channelNumber);
        destination.wiFiBand = GetWiFiBand(source.wlanChannel);
        destination.rssi = static_cast<int8_t>(source.rssiValue);

        NSData * ssidData = source.ssidData;
        destination.ssidLen = static_cast<uint8_t>(std::min(ssidData.length, DeviceLayer::Internal::kMaxWiFiSSIDLength));
        memcpy(destination.ssid, ssidData.bytes, destination.ssidLen);

        // source.bssid looks like "00:00:00:00:00:00" if it's not nil.
        NSString * bssid = source.bssid;
        // 3 chars per byte, except the last byte.
        if (bssid.length == 3 * sizeof(destination.bssid) - 1) {
            const char * chars = bssid.UTF8String;
            for (size_t i = 0; i < sizeof(destination.bssid); ++i) {
                Encoding::HexToBytes(&chars[3 * i], 2, &destination.bssid[i], 1);
            }
        }
    }

    WiFiSecurity GetWiFiSecurity(CWNetwork * network)
    {
        if ([network supportsSecurity:kCWSecurityNone]) {
            return WiFiSecurity::kUnencrypted;
        }

        if ([network supportsSecurity:kCWSecurityWEP]) {
            return WiFiSecurity::kWep;
        }

        if ([network supportsSecurity:kCWSecurityWPAPersonal]) {
            return WiFiSecurity::kWpaPersonal;
        }

        if ([network supportsSecurity:kCWSecurityWPA2Personal]) {
            return WiFiSecurity::kWpa2Personal;
        }

        if ([network supportsSecurity:kCWSecurityWPA3Personal]) {
            return WiFiSecurity::kWpa3Personal;
        }

        // If the value is not one of the preceding, it is unclear about how to map it.
        return WiFiSecurity::kUnencrypted;
    }

    WiFiBand GetWiFiBand(CWChannel * channel)
    {
        if (channel.channelBand == kCWChannelBand2GHz) {
            return WiFiBand::k2g4;
        }

        if (channel.channelBand == kCWChannelBand5GHz) {
            return WiFiBand::k5g;
        }

        // If the value is not one of the preceding, it is unclear about how to map it.
        return WiFiBand::k2g4;
    }
};

} // namespace

namespace chip {
namespace DeviceLayer {
    namespace NetworkCommissioning {
        CHIP_ERROR DarwinWiFiDriver::Init(BaseDriver::NetworkStatusChangeCallback * networkStatusChangeCallback)
        {
            auto & configurationMgr = ConfigurationManagerImpl::GetDefaultInstance();
            auto & connectivityMgr = ConnectivityMgrImpl();

            ReturnErrorOnFailure(configurationMgr.GetWiFiNetworkInformations(mNetwork));
            if (!connectivityMgr.IsWiFiStationConnected() && connectivityMgr.IsWiFiStationProvisioned()) {
                LogErrorOnFailure(connectivityMgr.ConnectWiFiNetwork(mNetwork));
            }

            mStatusChangeCallback = networkStatusChangeCallback;
            return CHIP_NO_ERROR;
        }

        void DarwinWiFiDriver::Shutdown() { mStatusChangeCallback = nullptr; }

        NetworkIterator * DarwinWiFiDriver::GetNetworks() { return new DarwinWiFiNetworkIterator(); }

        uint8_t DarwinWiFiDriver::GetMaxNetworks() { return kMaxNetworks; }

        uint8_t DarwinWiFiDriver::GetScanNetworkTimeoutSeconds() { return kScanNetworkTimeoutSeconds; }

        uint8_t DarwinWiFiDriver::GetConnectNetworkTimeoutSeconds() { return kConnectNetworkTimeoutSeconds; }

        CHIP_ERROR DarwinWiFiDriver::CommitConfiguration()
        {
            return ConfigurationManagerImpl::GetDefaultInstance().StoreWiFiNetworkInformations(mNetwork);
        }

        CHIP_ERROR DarwinWiFiDriver::RevertConfiguration()
        {
            mNetwork.Reset();
            return ConfigurationManagerImpl::GetDefaultInstance().GetWiFiNetworkInformations(mNetwork);
        }

        Status DarwinWiFiDriver::AddOrUpdateNetwork(
            ByteSpan ssid, ByteSpan credentials, MutableCharSpan & outText, uint8_t & outIndex)
        {
            outText.reduce_size(0);
            outIndex = 0;
            VerifyOrReturnError(CHIP_NO_ERROR == mNetwork.Update(ssid, credentials), Status::kUnknownError);

            return Status::kSuccess;
        }

        Status DarwinWiFiDriver::RemoveNetwork(ByteSpan ssid, MutableCharSpan & outText, uint8_t & outIndex)
        {
            outText.reduce_size(0);
            outIndex = 0;
            VerifyOrReturnError(mNetwork.Match(ssid), Status::kNetworkIDNotFound);

            mNetwork.Reset();

            return Status::kSuccess;
        }

        Status DarwinWiFiDriver::ReorderNetwork(ByteSpan ssid, uint8_t index, MutableCharSpan & outText)
        {
            outText.reduce_size(0);
            VerifyOrReturnError(index == 0, Status::kOutOfRange);
            VerifyOrReturnError(mNetwork.Match(ssid), Status::kNetworkIDNotFound);

            // We only support one network, so reorder is actually no-op.
            return Status::kSuccess;
        }

        void DarwinWiFiDriver::ConnectNetwork(ByteSpan ssid, ConnectCallback * callback)
        {
            VerifyOrReturn(mNetwork.Match(ssid), DispatchConnectNetworkResponse(callback, Status::kNetworkIDNotFound));

            auto err = ConnectivityMgrImpl().ConnectWiFiNetwork(mNetwork);
            VerifyOrReturn(CHIP_ERROR_KEY_NOT_FOUND != err, DispatchConnectNetworkResponse(callback, Status::kNetworkNotFound));
            VerifyOrReturn(CHIP_ERROR_NOT_CONNECTED != err, DispatchConnectNetworkResponse(callback, Status::kAuthFailure));
            VerifyOrReturn(CHIP_NO_ERROR == err, DispatchConnectNetworkResponse(callback, Status::kUnknownError));

            DispatchConnectNetworkResponse(callback, Status::kSuccess);
        }

        void DarwinWiFiDriver::DispatchConnectNetworkResponse(ConnectCallback * callback, Status status)
        {
            if (callback) {
                callback->OnResult(status, CharSpan(), 0);
            }
        }

        void DarwinWiFiDriver::ScanNetworks(ByteSpan ssid, ScanCallback * callback)
        {
            VerifyOrReturn(callback != nullptr); // Not much we can do.

            auto WiFiClient = [CWWiFiClient sharedWiFiClient];
            VerifyOrReturn(WiFiClient != nil, DispatchScanNetworksResponse(callback, Status::kUnknownError));

            CWInterface * interface = [WiFiClient interface];
            VerifyOrReturn(interface != nil, DispatchScanNetworksResponse(callback, Status::kUnknownError));

            NSError * error = nil;
            NSData * ssidData = ssid.size() ? [NSData dataWithBytes:ssid.data() length:ssid.size()] : nil;
            auto networks = [[interface scanForNetworksWithSSID:ssidData error:&error] allObjects];
            VerifyOrReturn(error == nil, DispatchScanNetworksResponse(callback, Status::kUnknownError));
            VerifyOrReturn([networks count] != 0, DispatchScanNetworksResponse(callback, Status::kSuccess));

            DarwinScanResponseIterator iter(networks);
            DispatchScanNetworksResponse(callback, Status::kSuccess, &iter);
        }

        void DarwinWiFiDriver::DispatchScanNetworksResponse(
            ScanCallback * callback, Status status, Iterator<WiFiScanResponse> * responses)
        {
            if (callback) {
                callback->OnFinished(status, CharSpan(), responses);
            }
        }
    } // namespace NetworkCommissioning
} // namespace DeviceLayer
} // namespace chip
