/**
 *
 *    Copyright (c) 2021 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.
 */

#import "MTRThreadOperationalDataset.h"

#include "MTRLogging.h"
#include <lib/support/Span.h>
#include <lib/support/ThreadOperationalDataset.h>

size_t const MTRSizeThreadNetworkName = chip::Thread::kSizeNetworkName;
size_t const MTRSizeThreadExtendedPANID = chip::Thread::kSizeExtendedPanId;
size_t const MTRSizeThreadExtendedPanId = MTRSizeThreadExtendedPANID;
size_t const MTRSizeThreadMasterKey = chip::Thread::kSizeMasterKey;
size_t const MTRSizeThreadPSKc = chip::Thread::kSizePSKc;
size_t const MTRSizeThreadPANID = 2; // Thread's PAN ID is 2 bytes

@interface MTRThreadOperationalDataset ()

@property (readonly) chip::Thread::OperationalDataset cppThreadOperationalDataset;
@property (nonatomic, copy) NSNumber * channelNumber;

@end

@implementation MTRThreadOperationalDataset

- (instancetype _Nullable)initWithNetworkName:(NSString *)networkName
                                extendedPANID:(NSData *)extendedPANID
                                    masterKey:(NSData *)masterKey
                                         PSKc:(NSData *)PSKc
                                channelNumber:(NSNumber *)channelNumber
                                        panID:(NSData *)panID
{
    if (self = [super init]) {
        _networkName = [networkName copy];
        _extendedPANID = [extendedPANID copy];
        _masterKey = [masterKey copy];
        _PSKc = [PSKc copy];
        _channelNumber = [channelNumber copy];
        _panID = [panID copy];
        _cppThreadOperationalDataset = chip::Thread::OperationalDataset();
        if ([self _populateCppOperationalDataset]) {
            return self;
        }
    }
    return nil;
}

- (BOOL)_populateCppOperationalDataset
{
    _cppThreadOperationalDataset.Clear();
    _cppThreadOperationalDataset.SetNetworkName([self.networkName cStringUsingEncoding:NSUTF8StringEncoding]);

    if (![self _checkDataLength:self.extendedPANID expectedLength:MTRSizeThreadExtendedPANID]) {
        MTR_LOG_ERROR("Invalid ExtendedPANID");
        return NO;
    }
    uint8_t extendedPanId[MTRSizeThreadExtendedPANID];
    [self.extendedPANID getBytes:&extendedPanId length:MTRSizeThreadExtendedPANID];
    _cppThreadOperationalDataset.SetExtendedPanId(extendedPanId);

    if (![self _checkDataLength:self.masterKey expectedLength:MTRSizeThreadMasterKey]) {
        MTR_LOG_ERROR("Invalid MasterKey");
        return NO;
    }
    uint8_t masterKey[MTRSizeThreadMasterKey];
    [self.masterKey getBytes:&masterKey length:MTRSizeThreadMasterKey];
    _cppThreadOperationalDataset.SetMasterKey(masterKey);

    if (![self _checkDataLength:self.PSKc expectedLength:MTRSizeThreadPSKc]) {
        MTR_LOG_ERROR("Invalid PKSc");
        return NO;
    }
    uint8_t PSKc[MTRSizeThreadPSKc];
    [self.PSKc getBytes:&PSKc length:MTRSizeThreadPSKc];
    _cppThreadOperationalDataset.SetPSKc(PSKc);

    _cppThreadOperationalDataset.SetChannel([self.channelNumber unsignedShortValue]);

    // Thread's PAN ID is 2 bytes
    if (![self _checkDataLength:self.panID expectedLength:MTRSizeThreadPANID]) {
        MTR_LOG_ERROR("Invalid PAN ID");
        return NO;
    }
    uint16_t panID;
    memcpy(&panID, [self.panID bytes], MTRSizeThreadPANID);
    // The underlying CPP class assumes Big Endianness for the panID
    _cppThreadOperationalDataset.SetPanId(CFSwapInt16HostToBig(panID));

    return YES;
}

- (BOOL)_checkDataLength:(NSData *)data expectedLength:(size_t)expectedLength
{
    if (data.length != expectedLength) {
        MTR_LOG_ERROR("Length Check Failed. Length:%tu is incorrect, must be %tu", data.length, expectedLength);
        return NO;
    }
    return YES;
}

- (instancetype _Nullable)initWithData:(NSData *)data
{
    chip::ByteSpan span = chip::ByteSpan((uint8_t *) data.bytes, data.length);
    auto dataset = chip::Thread::OperationalDataset();
    CHIP_ERROR error = dataset.Init(span);
    if (error != CHIP_NO_ERROR) {
        MTR_LOG_ERROR("Failed to parse data, cannot construct Operational Dataset. %s", chip::ErrorStr(error));
        return nil;
    }
    // len+1 for null termination
    char networkName[MTRSizeThreadNetworkName + 1];
    uint8_t pskc[MTRSizeThreadPSKc];
    uint8_t extendedPANID[MTRSizeThreadExtendedPANID];
    uint8_t masterKey[MTRSizeThreadMasterKey];
    uint16_t panID;
    uint16_t channel;
    dataset.GetNetworkName(networkName);
    dataset.GetExtendedPanId(extendedPANID);
    dataset.GetMasterKey(masterKey);
    dataset.GetPSKc(pskc);
    dataset.GetPanId(panID);
    dataset.GetChannel(channel);
    panID = CFSwapInt16BigToHost(panID);

    return [self initWithNetworkName:[NSString stringWithUTF8String:networkName]
                       extendedPANID:[NSData dataWithBytes:extendedPANID length:MTRSizeThreadExtendedPANID]
                           masterKey:[NSData dataWithBytes:masterKey length:MTRSizeThreadMasterKey]
                                PSKc:[NSData dataWithBytes:pskc length:MTRSizeThreadPSKc]
                       channelNumber:@(channel)
                               panID:[NSData dataWithBytes:&panID length:sizeof(uint16_t)]];
}

- (NSData *)data
{
    chip::ByteSpan span = _cppThreadOperationalDataset.AsByteSpan();
    return [NSData dataWithBytes:span.data() length:span.size()];
}

@end

@implementation MTRThreadOperationalDataset (Deprecated)

- (void)setChannel:(uint16_t)channel
{
    self.channelNumber = @(channel);
}

- (uint16_t)channel
{
    return [self.channelNumber unsignedShortValue];
}

- (nullable instancetype)initWithNetworkName:(NSString *)networkName
                               extendedPANID:(NSData *)extendedPANID
                                   masterKey:(NSData *)masterKey
                                        PSKc:(NSData *)PSKc
                                     channel:(uint16_t)channel
                                       panID:(NSData *)panID
{
    return [self initWithNetworkName:networkName
                       extendedPANID:extendedPANID
                           masterKey:masterKey
                                PSKc:PSKc
                       channelNumber:@(channel)
                               panID:panID];
}

@end
