//
//  ELMeatProbeBoxBleParser.m
//  AILinkBleSDK
//
//  Created by LarryZhang on 2023/2/16.
//

#import "ELMeatProbeBoxBleParser.h"
#import "ELMeatProbeBoxBleHeader.h"
#import <objc/runtime.h>

@interface ELMeatProbeBoxBleParser ()

@property (nonatomic, strong) ELMeatProbeBoxBleBoxStatusModel *boxStatusModel;

@property (nonatomic, strong) ELMeatProbeBoxBleProbeStatusModel *probeStatusModel;

@end

@implementation ELMeatProbeBoxBleParser

- (instancetype)init {
    if (self = [super init]) {
        _boxStatusModel = [[ELMeatProbeBoxBleBoxStatusModel alloc] init];
        _probeStatusModel = [[ELMeatProbeBoxBleProbeStatusModel alloc] init];
    }
    return self;
}

#pragma mark - 解析包

- (void)parseA7Payload:(NSData *)payloadData {
    UInt8 *bytes = (Byte *)payloadData.bytes;
//    UInt8 len = payloadData.length;
    UInt8 cmd = bytes[0];

    switch (cmd) {
        case ELMeatProbeBoxCMDMcuUploadStatus_Type02:
            [self handelMcuUploadStatus:payloadData];
            break;
        case ELMeatProbeBoxCMDCustomData_Type03:
            [self handelCustomData:payloadData];
            break;
        case ELMeatProbeBoxCMDAppSwitchUnit_Type04:
            [self handelSwitchUnit:payloadData];
            break;
        default:
            break;
    }
}

- (void)handelCustomData:(NSData *)payloadData {
    UInt8 *bytes = (Byte *)payloadData.bytes;
    UInt8 len = payloadData.length;
    
    BOOL state = bytes[1];
    NSData *mac = [payloadData subdataWithRange:NSMakeRange(2, 6)];
    Byte *bytesMac = (Byte *)mac.bytes;
    NSString *macString = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", bytesMac[5], bytesMac[4], bytesMac[3], bytesMac[2], bytesMac[1], bytesMac[0]];
    NSData *customData = [payloadData subdataWithRange:NSMakeRange(8, len - 8)];
    
    if (self.delegate && [self.delegate respondsToSelector:@selector(meatProbeBoxBleParser:state:mac:customData:)]) {
        [self.delegate meatProbeBoxBleParser:self state:state mac:macString customData:customData];
    }
}

- (void)handelSwitchUnit:(NSData *)payloadData {
    UInt8 *bytes = (Byte *)payloadData.bytes;
    //UInt8 len = payloadData.length;
    
    ELDeviceTemperatureUnit unit = bytes[1];
    
    if (self.delegate && [self.delegate respondsToSelector:@selector(meatProbeBoxBleParser:unit:)]) {
        [self.delegate meatProbeBoxBleParser:self unit:unit];
    }
}

- (void)handelMcuUploadStatus:(NSData *)payloadData {
    UInt8 *bytes = (Byte *)payloadData.bytes;
    UInt8 len = payloadData.length;
    
    _boxStatusModel.version = bytes[1];
    
    UInt8 probeMaxCount = bytes[2];
    if (probeMaxCount < 1) {
        return;//探针数排错
    }
    _boxStatusModel.probeMaxCount = probeMaxCount;
    UInt8 probeCount = bytes[3];
    if (probeCount > probeMaxCount) {
        return;//探针数排错
    }
    if (len < 1 + 8 + 16 * probeCount) {
        return;//数据长度排错
    }
    
    _boxStatusModel.probeCount = probeCount;
    
    _boxStatusModel.batteryStatus = bytes[4] >> 7;
    _boxStatusModel.batteryPercent = bytes[4] & 0x7F;
    _boxStatusModel.unit = bytes[5];
    UInt8 reserved = bytes[6];
    reserved = bytes[7];
    reserved = bytes[8];
    
    double timestamp = [[NSDate date] timeIntervalSince1970];
    _boxStatusModel.timestamp = timestamp;
    
//    for (int i=0, j=9+16*i; i<probeCount; i++) {
    for (int i=0, j=9+16*i; i<probeMaxCount; i++) {
        _probeStatusModel.index = bytes[j+0];
        _probeStatusModel.dataIndex = i;
        
        _probeStatusModel.macData = [payloadData subdataWithRange:NSMakeRange(j+1, 6)];
        _probeStatusModel.macString = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", bytes[j+6], bytes[j+5], bytes[j+4], bytes[j+3], bytes[j+2], bytes[j+1]];
        if ([_probeStatusModel.macString isEqualToString:@"00:00:00:00:00:00"] || [_probeStatusModel.macString isEqualToString:@"FF:FF:FF:FF:FF:FF"]) {
            continue;
        }
        
        if (i >= probeCount) {
            [_probeStatusModel makeInvalid];
            _probeStatusModel.timestamp = timestamp;
            if (self.delegate && [self.delegate respondsToSelector:@selector(meatProbeBoxBleParser:boxStatus:probeStatus:offline:)]) {
                [self.delegate meatProbeBoxBleParser:self boxStatus:_boxStatusModel probeStatus:_probeStatusModel offline:YES];
            }
            continue;
        }
        
        UInt16 temp = (bytes[j+7] << 8) | bytes[j+8];
        _probeStatusModel.internalTemperatureRaw = temp;
        _probeStatusModel.internalTemperatureUnit = (temp & 0x8000) ? ELDeviceTemperatureUnit_F : ELDeviceTemperatureUnit_C;
        _probeStatusModel.internalTemperature = (temp & 0x4000) ? -(temp & 0x3FFF) : (temp & 0x3FFF);
        
        temp = (bytes[j+9] << 8) | bytes[j+10];
        _probeStatusModel.ambientTemperatureRaw = temp;
        _probeStatusModel.ambientTemperatureUnit = (temp & 0x8000) ? ELDeviceTemperatureUnit_F : ELDeviceTemperatureUnit_C;
        _probeStatusModel.ambientTemperature = (temp & 0x4000) ? -(temp & 0x3FFF) : (temp & 0x3FFF);
#if DEBUG
//        _probeStatusModel.ambientTemperature += 40;
#endif
        
        UInt8 battery = bytes[j+11];
        _probeStatusModel.batteryRaw = battery;
        _probeStatusModel.batteryStatus = battery >> 7;
        _probeStatusModel.batteryPercent = battery & 0x7F;
        
        _probeStatusModel.insertStatusRaw = bytes[j+12];
        
        _probeStatusModel.timestamp = timestamp;
        if (self.delegate && [self.delegate respondsToSelector:@selector(meatProbeBoxBleParser:boxStatus:probeStatus:offline:)]) {
            [self.delegate meatProbeBoxBleParser:self boxStatus:_boxStatusModel probeStatus:_probeStatusModel offline:NO];
        }
    }
    
}

@end

@implementation ELMeatProbeBoxBleBoxStatusModel

#pragma mark  ---- description

- (NSString *)description {
    NSMutableString *desc = [NSStringFromClass([self class]) stringByAppendingString:@": {\n"].mutableCopy;
    unsigned int count;
    Ivar *ivar = class_copyIvarList([self class], &count);
    for (int i = 0 ; i < count ; i++) {
        Ivar iv = ivar[i];
        const char *name = ivar_getName(iv);
        NSString *strName = [NSString stringWithUTF8String:name];
        //利用KVC取值
        id value = [self valueForKey:strName];
        [desc appendString:[NSString stringWithFormat:@"    %@: %@,\n", strName, value]];
    }
    free(ivar);
    
    [desc appendString:@"}"];
    return desc;
}

- (NSString *)debugDescription {
    return [self description];
}

@end

@implementation ELMeatProbeBoxBleProbeStatusModel

//数据无效
- (void)makeInvalid {
    self.internalTemperatureRaw = 0xFFFF;
    self.internalTemperatureUnit = 0;
    self.internalTemperature = 0;
    self.ambientTemperatureRaw = 0xFFFF;
    self.ambientTemperatureUnit = 0;
    self.ambientTemperature = 0;
    self.batteryRaw = 0xFF;
    self.batteryStatus = 0;
    self.batteryPercent = 0;
    self.insertStatusRaw = 0;
}

#pragma mark  ---- description

- (NSString *)description {
    NSMutableString *desc = [NSStringFromClass([self class]) stringByAppendingString:@": {\n"].mutableCopy;
    unsigned int count;
    Ivar *ivar = class_copyIvarList([self class], &count);
    for (int i = 0 ; i < count ; i++) {
        Ivar iv = ivar[i];
        const char *name = ivar_getName(iv);
        NSString *strName = [NSString stringWithUTF8String:name];
        //利用KVC取值
        id value = [self valueForKey:strName];
        [desc appendString:[NSString stringWithFormat:@"    %@: %@,\n", strName, value]];
    }
    free(ivar);
    
    [desc appendString:@"}"];
    return desc;
}

- (NSString *)debugDescription {
    return [self description];
}

@end

