//
//  NibssIsoProcessor.m
//  MyBluetoothTest
//
//  Created by Emmanuel Adeyemi on 2/9/16.
//  Copyright © 2016 Emmanuel Adeyemi. All rights reserved.
//

#import "NibssIsoProcessor.h"
#import "NSString+HexUtil.h"
#import "PaypadKeyManager.h"
#import "NibssSocketManager.h"
#import "Global.h"
#import "PurchaseResponse.h"

@implementation NibssIsoProcessor


+(PurchaseResponse *)process:(PurchaseRequest *)request{
    
    ISOMessage *isoMsg = [[ISOMessage alloc] init];
    [isoMsg setMTI:@"0200"];
    
//    ismsg.setField(2, field2);
//    ismsg.setField(3, field3);
//    ismsg.setField(4, field4);
//    ismsg.setField(7, field7);
//    ismsg.setField(11, field11);
//    ismsg.setField(12, field12);
//    ismsg.setField(13, field13);
//    ismsg.setField(14, field14);
//    ismsg.setField(18, field18);
//    ismsg.setField(22, field22);
//    ismsg.setField(23, field23);
//    ismsg.setField(25, field25);
//    ismsg.setField(26, field26);
//    ismsg.setField(28, field28);
//    ismsg.setField(32, field32);
//    ismsg.setField(35, field35);
//    ismsg.setField(37, field37);
//    ismsg.setField(40, field40);
//    ismsg.setField(41, field41);
//    ismsg.setField(42, field42);
//    ismsg.setField(43, field43);
//    ismsg.setField(49, field49);
//    
//    if (request.getPinData() != null) {
//        ismsg.setField(52, field52);
//    }
//    
//    ismsg.setField(55, field55);
//    ismsg.setField(59, field59);
//    ismsg.setField(123, field123);
//    ismsg.setField(128, field128);
    
    
    if([[request getPinData] length] > 0){
    
        isoMsg.bitmap = [[ISOBitmap alloc]
                         initWithGivenDataElements:@[@"DE02",@"DE03",@"DE04",@"DE07",@"DE11",@"DE12",@"DE13",@"DE14",@"DE18",
                                                     @"DE22",@"DE23",@"DE25",@"DE26",@"DE28",@"DE32",@"DE35",@"DE37",@"DE40",
                                                     @"DE41",@"DE42",@"DE43",@"DE49",@"DE52",@"DE55",@"DE59",@"DE123",@"DE128"]];
    }else{
        isoMsg.bitmap = [[ISOBitmap alloc]
                         initWithGivenDataElements:@[@"DE02",@"DE03",@"DE04",@"DE07",@"DE11",@"DE12",@"DE13",@"DE14",@"DE18",
                                                     @"DE22",@"DE23",@"DE25",@"DE26",@"DE28",@"DE32",@"DE35",@"DE37",@"DE40",
                                                     @"DE41",@"DE42",@"DE43",@"DE49",@"DE55",@"DE59",@"DE123",@"DE128"]];
    }
    
    [isoMsg addDataElement:@"DE02" withValue:[request getPan]];
    [isoMsg addDataElement:@"DE03" withValue:[request getProcessingCode]];
    [isoMsg addDataElement:@"DE04" withValue:[request getTransactionAmount]];
    [isoMsg addDataElement:@"DE07" withValue:[request getTransmissionDateTime]];
    [isoMsg addDataElement:@"DE11" withValue:[request getStan]];
    [isoMsg addDataElement:@"DE12" withValue:[request getLocalTransactionTime]];
    [isoMsg addDataElement:@"DE13" withValue:[request getLocalTransactionDate]];
    [isoMsg addDataElement:@"DE14" withValue:[request getCardExpirationDate]];
    [isoMsg addDataElement:@"DE18" withValue:[request getMerchantType]];
    [isoMsg addDataElement:@"DE22" withValue:[request getPosEntryMode]];
    [isoMsg addDataElement:@"DE23" withValue:[request getCardSequenceNumber]];
    [isoMsg addDataElement:@"DE25" withValue:[request getPosConditionCode]];
    [isoMsg addDataElement:@"DE26" withValue:[request getPosPinCaptureCode]];
    [isoMsg addDataElement:@"DE28" withValue:[request getTransactionFee]];
    [isoMsg addDataElement:@"DE32" withValue:[request getAcquiringInstIdCode]];
    [isoMsg addDataElement:@"DE35" withValue:[request getTrack2Data]];
    [isoMsg addDataElement:@"DE37" withValue:[request getRetrievalReferenceNumber]];
    [isoMsg addDataElement:@"DE40" withValue:[request getServiceRestrictionCode]];
    [isoMsg addDataElement:@"DE41" withValue:[request getTerminalId]];
    [isoMsg addDataElement:@"DE42" withValue:[request getCardAcceptorIdCode]];
    [isoMsg addDataElement:@"DE43" withValue:[request getCardAcceptorNameLocation]];
    [isoMsg addDataElement:@"DE49" withValue:[request getCurrencyCode]];
    
    if([[request getPinData] length] > 0){
        [isoMsg addDataElement:@"DE52" withValue:[request getPinData]];
    }
    
    [isoMsg addDataElement:@"DE55" withValue:[request getIccData]];
    [isoMsg addDataElement:@"DE59" withValue:[request getTransportData]];
    [isoMsg addDataElement:@"DE123" withValue:[request getPosDataCode]];
    
    
    NSData *d = [@"0" stringToData];
    NSString *tempStr =  [[NSString alloc] initWithData:d encoding:NSUTF8StringEncoding] ;
    
    [isoMsg addDataElement:@"DE128" withValue:[NSString stringWithFormat:@"%-64@",tempStr]];
    
    NSString *builtMsg = [isoMsg buildIsoMessage];
    
    NSLog(@"Initial build %@",builtMsg);
    
    NSData *data = [builtMsg dataUsingEncoding:NSUTF8StringEncoding];
    
    NSInteger len = data.length;
    
    NSData *temp = [[NSData alloc] init];
    
    if(len >= 64){
        temp = [data subdataWithRange:NSMakeRange(0, len - 64)];
    }
    
    NSString *sessionKey = [[NSUserDefaults standardUserDefaults] objectForKey:TSK_LOCATION];
    
//    NSData *dd = [sessionKey dataUsingEncoding:NSUTF8StringEncoding];
    
    sessionKey = [sessionKey stringByReplacingOccurrencesOfString:@" " withString:@""];
    
    NSString *hashValue = [NibssIsoProcessor generateHash256Value:temp sessionKey:[sessionKey stringToData]];
    
    [isoMsg addDataElement:@"DE128" withValue:hashValue];
    
    builtMsg = [isoMsg buildIsoMessage];
    
//    builtMsg = [NSString stringWithFormat:@"%@\r\n",builtMsg]
    
    data = [builtMsg dataUsingEncoding:NSUTF8StringEncoding];
    
    NSMutableData *message = [data mutableCopy];
    
    NibssSocketManager *nibssSocketManager = [[NibssSocketManager alloc] init];
    
    [nibssSocketManager sendMessageToNibss:message];
    
    NSString *responseCode = [[NSUserDefaults standardUserDefaults] objectForKey:RESPONSE_CODE];
    
    PurchaseResponse *presponse = [[PurchaseResponse alloc] init];
    
    presponse.field39 = responseCode;
    
    NSString *responseMessage = [PurchaseResponse getResponseString:responseCode];
    
    
    if([responseCode isEqualToString:@"XX"])
        presponse.responseMessage = @" UNCOMPLETED \n TRANSACTIONS";
    else
        presponse.responseMessage = responseMessage;
    
    
    return presponse;
    
//    
//    uint8_t *readBytes = (uint8_t *)[message mutableBytes];
//    //    readBytes += byteIndex; // instance variable to move pointer
//    int data_len = [message length];
//    
//    uint8_t header[2];
//    
//    header[0] = (uint8_t)data_len >> 8;
//    header[1] = (uint8_t)data_len;
//    
//    len = ((data_len - byteIndex >= 1024) ?
//                        1024 : (data_len-byteIndex));
//    uint8_t buf[len];
//    memcpy(buf, &readBytes, len);
    
    
}


+(NSString *)generateHash256Value:(NSData *)iso
                       sessionKey:(NSData *)sessionKey{
    
    
//    CC_SHA256_DIGEST_LENGTH
    
    CC_SHA256_CTX ctx;
    
    uint8_t finalKey[CC_SHA256_DIGEST_LENGTH];
    
    CC_SHA256_Init(&ctx);
    CC_SHA256_Update(&ctx, [sessionKey bytes], [sessionKey length]);
    CC_SHA256_Update(&ctx, [iso bytes],[iso length]);
    CC_SHA256_Final(finalKey, &ctx);
    
//    NSData *hashData =  [NSData dataWithBytes:finalKey length:32];
    
    NSData *response = [NSData dataWithBytes:finalKey length:CC_SHA256_DIGEST_LENGTH];
    
    NSString *hashedString = [NSString toHexString:finalKey length:CC_SHA256_DIGEST_LENGTH space:false];
    
    
//    NSString* hashedString = [NSString toHexString:finalKey length:32 space:false];
    
    if(hashedString.length < 64){
        
        u_long numOfZeros = 64 - hashedString.length;
        
        NSMutableString *zeros = [[NSMutableString alloc] init];
        
        for(int i =0; i < numOfZeros ; i++){
            zeros = [[zeros stringByAppendingString:@"0"] mutableCopy];
        }
        
        hashedString = [NSString stringWithFormat:@"%@%@",zeros,hashedString];
    }
    
    return hashedString;
}

static NSString *hexToString(NSString * label, const void *data, size_t length)
{
    const char HEX[]="0123456789ABCDEF";
    char s[2000];
    for(int i=0;i<length;i++)
    {
        s[i*3]=HEX[((uint8_t *)data)[i]>>4];
        s[i*3+1]=HEX[((uint8_t *)data)[i]&0x0f];
        s[i*3+2]=' ';
    }
    s[length*3]=0;
    
    if(label)
        return [NSString stringWithFormat:@"%@(%d): %s",label,(int)length,s];
    else
        return [NSString stringWithCString:s encoding:NSUTF8StringEncoding];
}

@end
