//
//  RCTMPosControllerLabelPrinterProxy.m
//  RNBixolonBgateLibs
//
//  Created by JCLEE on 2021/08/27.
//

#import <Foundation/Foundation.h>
#import <React/RCTLog.h>
#import "RCTMPosControllerLabelPrinterProxy.h"

@import frameworkMPosSDK;

@interface RCTMPosControllerLabelPrinterProxy()
@property MPosControllerLabelPrinter* printer;
@end

@implementation RCTMPosControllerLabelPrinterProxy
{
    bool hasListeners;
}

+ (BOOL)requiresMainQueueSetup {
    return NO;
}

- (id)init{
    if((self=[super init])){
        _printer = [MPosControllerLabelPrinter new];
#ifdef DEBUG
        [MPosControllerLabelPrinter setEnableLog:YES saveFile:NO saveToHex:NO];
#endif
        [[NSNotificationCenter defaultCenter] removeObserver: self];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusNotificationHandler:) name: @"OutputCompletedEvent" object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusNotificationHandler:) name: @"DataEvent" object:nil];
    }
    
    return self;
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver: self];
}

- (void)startObserving {
    RCTLogInfo(@"startObserving");
    hasListeners = YES;
}

- (void)stopObserving {
    RCTLogInfo(@"stopObserving");
    hasListeners = NO;
}

- (NSArray<NSString*>*)supportedEvents {
    return @[@"LabelPrinterOutputCompletedEvent", @"LabelPrinterDataEvent"];
}

RCT_EXPORT_METHOD(selectInterface:(NSInteger)interfaceType
                  address:(NSString*)address
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer selectInterface:interfaceType address:address];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}


RCT_EXPORT_METHOD(selectCommandMode:(NSInteger)commandMode
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer selectCommandMode:commandMode];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(openService:(NSInteger)deviceID
                  timeout:(NSInteger)timeout
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    [_printer setTimeout: timeout];
    MPOS_RESULT result = [_printer openService:deviceID];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(closeService:(NSInteger)timeout
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer closeService:timeout];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setTransaction:(NSInteger)mode
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setTransaction:mode];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setReadMode:(NSInteger)mode
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setReadMode:mode];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setKeepNetworkConnection:(NSInteger)enable
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    [_printer setKeepNetworkConnection:enable];
    resolve([NSNumber numberWithInteger:0]);
}

RCT_EXPORT_METHOD(getDeviceId:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    NSInteger deviceId = [_printer getDeviceId];
    if(deviceId < 0){
        reject(@"FAIL", [NSString stringWithFormat:@"DEVICE_ID: %ld",(long)deviceId], nil);
        return;
    }
    resolve([NSNumber numberWithInteger:deviceId]);
}

RCT_EXPORT_METHOD(isOpen:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    NSInteger isOpen = [_printer isOpen];
    resolve([NSNumber numberWithInteger:isOpen]);
}

RCT_EXPORT_METHOD(getSDKVersion:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    resolve([_printer getSDKVersion]);
}

RCT_EXPORT_METHOD(directIO:(NSArray<NSNumber*>*)data
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    NSMutableData* dataToSend = [NSMutableData data];
    for(NSNumber* number in data){
        char byte = [number charValue];
        [dataToSend appendBytes: &byte length:1];
    }
    MPOS_RESULT result = [_printer directIO:dataToSend];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(checkPrinterStatus:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    NSInteger status = [_printer checkPrinterStatus];
    resolve([NSNumber numberWithInteger:status]);
}


RCT_EXPORT_METHOD(printBuffer:(NSInteger)numberOfCopies
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer printBuffer:numberOfCopies];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(printRawData:(NSArray<NSNumber*>*)data
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    NSMutableData* dataToSend = [NSMutableData data];
    for(NSNumber* number in data){
        char byte = [number charValue];
        [dataToSend appendBytes: &byte length:1];
    }
    MPOS_RESULT result = [_printer printRawData:dataToSend];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawTextDeviceFont:(NSString*)data
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  fontSelection:(NSString*)fontSelection
                  fontWidth:(NSInteger)fontWidth
                  fontHeight:(NSInteger)fontHeight
                  rightSpace:(NSInteger)rightSpace
                  rotation:(NSInteger)rotation
                  reverse:(NSInteger)reverse
                  bold:(NSInteger)bold
                  rightToLeft:(NSInteger)rightToLeft
                  alignment:(NSInteger)alignment
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawTextDeviceFont:data
                                                 xPos:xPos
                                                 yPos:yPos
                                        fontSelection:(char)[fontSelection UTF8String][0]
                                            fontWidth:fontWidth
                                           fontHeight:fontHeight
                                           rightSpace:rightSpace
                                             rotation:rotation
                                              reverse:(reverse > 0)
                                                 bold:(bold > 0)
                                          rightToLeft:rightToLeft
                                            alignment:alignment];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawTextVectorFont:(NSString*)data
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  fontSelection:(NSString*)fontSelection
                  fontWidth:(NSInteger)fontWidth
                  fontHeight:(NSInteger)fontHeight
                  rightSpace:(NSInteger)rightSpace
                  rotation:(NSInteger)rotation
                  reverse:(NSInteger)reverse
                  bold:(NSInteger)bold
                  italic:(NSInteger)italic
                  rightToLeft:(NSInteger)rightToLeft
                  alignment:(NSInteger)alignment
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawTextVectorFont:data
                                                 xPos:xPos
                                                 yPos:yPos
                                        fontSelection:(char)[fontSelection UTF8String][0]
                                            fontWidth:fontWidth
                                           fontHeight:fontHeight
                                           rightSpace:rightSpace
                                             rotation:rotation
                                              reverse:(reverse > 0)
                                                 bold:(bold > 0)
                                               italic:(italic > 0)
                                          rightToLeft:(rightToLeft > 0)
                                            alignment:alignment];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawBarcode1D:(NSString*)data
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  barcodeType:(NSInteger)barcodeType
                  widthNarrow:(NSInteger)widthNarrow
                  widthWide:(NSInteger)widthWide
                  height:(NSInteger)height
                  hri:(NSInteger)hri
                  quietZoneWidth:(NSInteger)quietZoneWidth
                  rotation:(NSInteger)rotation
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawBarcode1D:data
                                            xPos:xPos
                                            yPos:yPos
                                     barcodeType:barcodeType
                                     widthNarrow:widthNarrow
                                       widthWide:widthWide
                                          height:height
                                             hri:hri
                                  quietZoneWidth:quietZoneWidth
                                        rotation:rotation];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawBarcodeMaxiCode:(NSString*)data
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  mode:(NSInteger)mode
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawBarcodeMaxiCode:data
                                                  xPos:xPos
                                                  yPos:yPos
                                                  mode:mode];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawBarcodePDF417:(NSString*)data
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  maximumRowCount:(NSInteger)maximumRowCount
                  maximumColumnCount:(NSInteger)maximumColumnCount
                  errorCorrectionLevel:(NSInteger)errorCorrectionLevel
                  dataCompressionMethod:(NSInteger)dataCompressionMethod
                  hri:(NSInteger)hri
                  barcodeOriginPoint:(NSInteger)barcodeOriginPoint
                  moduleWidth:(NSInteger)moduleWidth
                  barHeight:(NSInteger)barHeight
                  rotation:(NSInteger)rotation
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawBarcodePDF417:data
                                                xPos:xPos
                                                yPos:yPos
                                     maximumRowCount:maximumRowCount
                                  maximumColumnCount:maximumColumnCount
                                errorCorrectionLevel:errorCorrectionLevel
                               dataCompressionMethod:dataCompressionMethod
                                                 hri:(hri > 0)
                                       startPosition:barcodeOriginPoint
                                         moduleWidth:moduleWidth
                                           barHeight:barHeight
                                            rotation:rotation];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawBarcodeQRCode:(NSString*)data
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  size:(NSInteger)size
                  model:(NSInteger)model
                  errorCorrectionLevel:(NSInteger)errorCorrectionLevel
                  rotation:(NSInteger)rotation
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawBarcodeQRCode:data
                                                xPos:xPos
                                                yPos:yPos
                                                size:size
                                               model:model
                                            eccLevel:errorCorrectionLevel
                                            rotation:rotation];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawBarcodeDataMatrix:(NSString*)data
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  size:(NSInteger)size
                  reverse:(NSInteger)reverse
                  rotation:(NSInteger)rotation
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawBarcodeDataMatrix:data
                                                    xPos:xPos
                                                    yPos:yPos
                                                    size:size
                                                 reverse:(reverse > 0)
                                                rotation:rotation];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawBarcodeAztec:(NSString*)data
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  size:(NSInteger)size
                  extendedChannel:(NSInteger)extendedChannel
                  eccLevel:(NSInteger)eccLevel
                  menuSymbol:(NSInteger)menuSymbol
                  numberOfSymbols:(NSInteger)numberOfSymbols
                  optionalID:(NSString*)optionalID
                  rotation:(NSInteger)rotation
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawBarcodeAztec:data
                                               xPos:xPos
                                               yPos:yPos
                                               size:size
                                    extendedChannel:(extendedChannel > 0)
                                           eccLevel:eccLevel
                                         menuSymbol:(menuSymbol > 0)
                                    numberOfSymbols:numberOfSymbols
                                         optionalID:optionalID
                                           rotation:rotation];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawBarcodeCode49:(NSString*)data
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  widthNarrow:(NSInteger)widthNarrow
                  widthWide:(NSInteger)widthWide
                  height:(NSInteger)height
                  hri:(NSInteger)hri
                  startingMode:(NSInteger)startingMode
                  rotation:(NSInteger)rotation
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawBarcodeCode49:data
                                                xPos:xPos
                                                yPos:yPos
                                         widthNarrow:widthNarrow
                                           widthWide:widthWide
                                              height:height
                                                 hri:hri
                                        startingMode:startingMode
                                            rotation:rotation];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawBarcodeCodaBlock:(NSString*)data
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  widthNarrow:(NSInteger)widthNarrow
                  widthWide:(NSInteger)widthWide
                  height:(NSInteger)height
                  securityLevel:(NSInteger)securityLevel
                  dataColumns:(NSInteger)dataColumns
                  mode:(NSString*)mode
                  rowsToEncode:(NSInteger)rowsToEncode
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawBarcodeCodaBlock:data
                                                   xPos:xPos
                                                   yPos:yPos
                                            widthNarrow:widthNarrow
                                              widthWide:widthWide
                                                 height:height
                                          securityLevel:(securityLevel > 0)
                                            dataColumns:dataColumns
                                                   mode:(char)[mode UTF8String][0]
                                           rowsToEncode:rowsToEncode];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawBarcodeMicroPDF:(NSString*)data
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  moduleWidth:(NSInteger)moduleWidth
                  height:(NSInteger)height
                  mode:(NSInteger)mode
                  rotation:(NSInteger)rotation
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawBarcodeMicroPDF:data
                                                  xPos:xPos
                                                  yPos:yPos
                                           moduleWidth:moduleWidth
                                                height:height
                                                  mode:mode
                                              rotation:rotation];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawBarcodeIMB:(NSString*)data
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  hri:(NSInteger)hri
                  rotation:(NSInteger)rotation
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawBarcodeIMB:data
                                             xPos:xPos
                                             yPos:yPos
                                              hri:(hri > 0)
                                         rotation:rotation];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawBarcodeMSI:(NSString*)data
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  widthNarrow:(NSInteger)widthNarrow
                  widthWide:(NSInteger)widthWide
                  height:(NSInteger)height
                  checkDigit:(NSInteger)checkDigit
                  printCheckDigit:(NSInteger)printCheckDigit
                  hri:(NSInteger)hri
                  rotation:(NSInteger)rotation
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawBarcodeMSI:data
                                             xPos:xPos
                                             yPos:yPos
                                      widthNarrow:widthNarrow
                                        widthWide:widthWide
                                           height:height
                                       checkDigit:checkDigit
                                  printCheckDigit:(printCheckDigit > 0)
                                              hri:hri
                                         rotation:rotation];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawBarcodePlessey:(NSString*)data
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  widthNarrow:(NSInteger)widthNarrow
                  widthWide:(NSInteger)widthWide
                  height:(NSInteger)height
                  printCheckDigit:(NSInteger)printCheckDigit
                  hri:(NSInteger)hri
                  rotation:(NSInteger)rotation
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawBarcodePlessey:data
                                                 xPos:xPos
                                                 yPos:yPos
                                          widthNarrow:widthNarrow
                                            widthWide:widthWide
                                               height:height
                                      printCheckDigit:(printCheckDigit > 0)
                                                  hri:hri
                                             rotation:rotation];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawBarcodeTLC39:(NSString*)data
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  widthNarrow:(NSInteger)widthNarrow
                  widthWide:(NSInteger)widthWide
                  height:(NSInteger)height
                  rowHeightMicroPDF417:(NSInteger)rowHeightMicroPDF417
                  narrowWidthOfMicroPDF417:(NSInteger)narrowWidthOfMicroPDF417
                  rotation:(NSInteger)rotation
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawBarcodeTLC39:data
                                               xPos:xPos
                                               yPos:yPos
                                        widthNarrow:widthNarrow
                                          widthWide:widthWide
                                             height:height
                             rowHeightOfMicroPDF417:rowHeightMicroPDF417
                           narrowWidthOfMicroPDF417:narrowWidthOfMicroPDF417
                                           rotation:rotation];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawBarcodeRSS:(NSString*)data
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  barcodeType:(NSInteger)barcodeType
                  magnification:(NSInteger)magnification
                  separatorHeight:(NSInteger)separatorHeight
                  height:(NSInteger)height
                  segmentWidth:(NSInteger)segmentWidth
                  rotation:(NSInteger)rotation
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawBarcodeRSS:data
                                             xPos:xPos
                                             yPos:yPos
                                      barcodeType:barcodeType
                                    magnification:magnification
                                  separatorHeight:separatorHeight
                                           height:height
                                     segmentWidth:segmentWidth
                                         rotation:rotation];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawBlock:(NSInteger)startPosX
                  startPosY:(NSInteger)startPosY
                  endPosX:(NSInteger)endPosX
                  endPosY:(NSInteger)endPosY
                  option:(NSString*)option
                  thickness:(NSInteger)thickness
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawBlock:startPosX
                                   startPosY:startPosY
                                     endPosX:endPosX
                                     endPosY:endPosY
                                      option:(char)[option UTF8String][0]
                                   thickness:thickness];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawCircle:(NSInteger)startPosX
                  startPosY:(NSInteger)startPosY
                  size:(NSInteger)size
                  multiplier:(NSInteger)multiplier
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawCircle:startPosX
                                    startPosY:startPosY
                                         size:size
                                   multiplier:multiplier];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawImageFile:(NSString*)fileName
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  width:(NSInteger)width
                  threshold:(NSInteger)threshold
                  ditheringType:(NSInteger)ditheringType
                  compressType:(NSInteger)compressType
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawImageFile:fileName
                                            xPos:xPos
                                            yPos:yPos
                                           width:width
                                       threshold:threshold
                                   ditheringType:ditheringType
                                    compressType:compressType];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawImage:(UIImage*)image
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  width:(NSInteger)width
                  threshold:(NSInteger)threshold
                  ditheringType:(NSInteger)ditheringType
                  compressType:(NSInteger)compressType
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawImage:image
                                            xPos:xPos
                                            yPos:yPos
                                           width:width
                                       threshold:threshold
                                   ditheringType:ditheringType
                                    compressType:compressType];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawBase64Image:(NSString*)base64String
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  width:(NSInteger)width
                  threshold:(NSInteger)threshold
                  ditheringType:(NSInteger)ditheringType
                  compressType:(NSInteger)compressType
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawBase64Image:base64String
                                            xPos:xPos
                                            yPos:yPos
                                           width:width
                                       threshold:threshold
                                   ditheringType:ditheringType
                                    compressType:compressType];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(drawPDFFile:(NSString*)filePath
                  xPos:(NSInteger)xPos
                  yPos:(NSInteger)yPos
                  width:(NSInteger)width
                  pageNumber:(NSInteger)pageNumber
                  threshold:(NSInteger)threshold
                  ditheringType:(NSInteger)ditheringType
                  compressType:(NSInteger)compressType
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer drawPDFFile:filePath
                                          posX:xPos
                                          posY:yPos
                                         width:width
                                    pageNumber:pageNumber
                                     threshold:threshold
                                 ditheringType:ditheringType
                                  compressType:compressType];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setTextEncoding:(NSInteger)chararacterset
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setTextEncoding:chararacterset];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setCharacterset:(NSInteger)chararacterset
                  internationalChararacterset:(NSInteger)internationalChararacterset
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setCharacterset:chararacterset internationalCharset:internationalChararacterset];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setPrintingType:(NSString*)printingType
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setPrintingType:(char)[printingType UTF8String][0]];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setMargin:(NSInteger)horizontalMargin
                  verticalMargin:(NSInteger)verticalMargin
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setMargin:horizontalMargin verticalMargin:verticalMargin];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setLength:(NSInteger)labelLength
                  gapLength:(NSInteger)gapLength
                  mediaType:(NSString*)mediaType
                  offsetLength:(NSInteger)offsetLength
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setLength:labelLength
                                   gapLength:gapLength
                                   mediaType:(char)[mediaType UTF8String][0]
                                offsetLength:offsetLength];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setWidth:(NSInteger)labelWidth
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setWidth:labelWidth];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setSpeed:(NSInteger)speed
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setSpeed:speed];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setDensity:(NSInteger)density
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setDensity:density];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setOrientation:(NSString*)orientation
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setOrientation:(char)[orientation UTF8String][0]];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setOffset:(NSInteger)offset
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setOffset:offset];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setCuttingPosition:(NSInteger)position
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setCuttingPosition:position];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setAutoCutter:(NSInteger)enableAutoCutter
                  cuttingPeriod:(NSInteger)cuttingPeriod
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setAutoCutter:(enableAutoCutter > 0) cuttingPeriod:cuttingPeriod];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setRewinder:(NSInteger)enable
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setRewinder:(enable > 0)];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setupRFID:(NSInteger)rfidType
                  numberOfRetries:(NSInteger)numberOfRetries
                  numberOfLabel:(NSInteger)numberOfLabel
                  radioPower:(NSInteger)radioPower
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setupRFID:rfidType
                             numberOfRetries:numberOfRetries
                               numberOfLabel:numberOfLabel
                                  radioPower:radioPower];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setEPCDataStructure:(NSInteger)totalSize
                  fieldSizes:(NSString*)fieldSizes
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setEPCDataStructure:totalSize fieldSizes:fieldSizes];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setRFIDPosition:(NSInteger)transPosition
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setRFIDPosition:transPosition];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(calibrateRFID:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer calibrateRFID];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(writeRFID:(NSInteger)dataType
                  startingBlockNumber:(NSInteger)startingBlockNumber
                  dataLength:(NSInteger)dataLength
                  data:(NSString*)data
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer writeRFID:dataType
                         startingBlockNumber:startingBlockNumber
                                  dataLength:dataLength
                                        data:data];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(setRFIDPassword:(NSString*)oldAccessPwd
                  oldKillPwd:(NSString*)oldKillPwd
                  newAccessPwd:(NSString*)newAccessPwd
                  newKillPwd:(NSString*)newKillPwd
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setRFIDPassword:oldAccessPwd
                                        oldKillPwd:oldKillPwd
                                      newAccessPwd:newAccessPwd
                                        newKillPwd:newKillPwd];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(lockRFID:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer lockRFID];
    NSString* resultMsg = [NSString stringWithFormat:@"RESULT_CODE: %ld",(long)result];
    if(result != MPOS_SUCCESS){
        reject(@"FAIL", resultMsg, nil);
        return;
    }
    resolve([NSNumber numberWithInteger:result]);
}

RCT_EXPORT_METHOD(getStatisticsData:(NSInteger)info
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    resolve([_printer getStatisticsData:info]);
}

RCT_EXPORT_METHOD(getPrinterDPI:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    resolve([NSNumber numberWithInteger:[_printer getPrinterDPI]]);
}

RCT_EXPORT_METHOD(getMaxWidth:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    resolve([NSNumber numberWithInteger:[_printer getMaxWidth]]);
}

RCT_EXPORT_METHOD(getSupportedSpeeds:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    resolve([_printer getSupportedSpeeds]);
}


RCT_EXPORT_METHOD(getModelName:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    resolve([_printer getModelName]);
}

RCT_EXPORT_METHOD(getFirmwareVersion:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    resolve([_printer getFirmwareVersion]);
}

- (void) statusNotificationHandler:(NSNotification*) notification{
    NSNumber* deviceId = (NSNumber*)[notification object];
    
    if([deviceId integerValue] != [_printer getDeviceId])
        return;
    
    __weak typeof(self) weakSelf = self;
    
    if ([[notification name] isEqualToString: @"OutputCompletedEvent"]){
        RCTLogInfo(@"LabelPrinterOutputCompletedEvent");
        if(hasListeners){
            [self sendEventWithName:@"LabelPrinterOutputCompletedEvent" body:@{@"deviceid":deviceId}];
        }
    }else if ([[notification name] isEqualToString: @"DataEvent"]){
        RCTLogInfo(@"DataEvent");
        
        NSMutableArray *allKeys = [[[notification userInfo] allKeys] mutableCopy];
        
        for (NSString *key in allKeys) {
            NSData* data = [[notification userInfo] objectForKey: key];
            
            dispatch_async(dispatch_get_main_queue(),^{
                typeof(self) strongSelf = weakSelf;
                
                if(strongSelf->hasListeners){
                    [strongSelf sendEventWithName:@"LabelPrinterDataEvent" body:@{
                        @"deviceid":deviceId,
                        @"data":[self convertNSDataToNSNumberArray:data]
                    }];
                }
            });
        }
    }
}

- (NSArray<NSNumber *> *)convertNSDataToNSNumberArray:(NSData *)data {
    const uint8_t *bytes = [data bytes];
    
    NSMutableArray<NSNumber *> *numberArray = [NSMutableArray array];
    
    for (NSUInteger i = 0; i < [data length]; i++) {
        NSNumber *number = [NSNumber numberWithUnsignedChar:bytes[i]];
        [numberArray addObject:number];
    }
    
    return [numberArray copy];
}

RCT_EXPORT_MODULE();

@end
