//  RCTMPosControllerPrinterProxy.m
//  RNBixolonBgateLibs
//  Created by JCLEE on 2021/08/11.

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

@import frameworkMPosSDK;

@interface RCTMPosControllerPrinterProxy()
@property MPosControllerPrinter* printer;
@end

@implementation RCTMPosControllerPrinterProxy
{
    bool hasListeners;
}

+ (BOOL)requiresMainQueueSetup {
    return NO;
}

- (id)init{
    if((self=[super init])){
        _printer = [MPosControllerPrinter new];
#ifdef DEBUG
        [MPosControllerPrinter setEnableLog:YES saveFile:NO saveToHex:NO];
#endif
        [[NSNotificationCenter defaultCenter] removeObserver: self];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusNotificationHandler:) name: @"StatusUpdateEvent" object:nil];
        [[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 @[@"StatusUpdateEvent",@"OutputCompletedEvent", @"PrinterDataEvent"];
}

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(asbEnable:(NSInteger)enable
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer asbEnable: enable > 0 ? YES : NO];
    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(setCharacterset:(NSInteger)characterset
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setCharacterset:characterset];
    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(setInternationalCharacterset:(NSInteger)characterset
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setInternationalCharacterset:characterset];
    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(cutPaper:(NSInteger)cutType
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer cutPaper:cutType];
    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(setPagemode:(NSInteger)mode
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setPagemode: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(setPagemodePrintArea:(NSInteger)x
                  y:(NSInteger)y
                  width:(NSInteger)width
                  height:(NSInteger)height
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setPagemodePrintArea:x y:y width:width height:height];
    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(setPagemodeDirection:(NSInteger)direction
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setPagemodeDirection:direction];
    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(setPagemodePosition:(NSInteger)x
                  y:(NSInteger)y
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer setPagemodePosition:x y:y];
    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(printText:(NSString*)data
                  fontType:(NSInteger)fontType
                  fontWidth:(NSInteger)fontWidth
                  fontHeight:(NSInteger)fontHeight
                  bold:(NSInteger)bold
                  underline:(NSInteger)underline
                  reverse:(NSInteger)reverse
                  alignment:(NSInteger)alignment
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer printText:data
                                    fontType:fontType
                                   fontWidth:fontWidth
                                  fontHeight:fontHeight
                                        bold:bold
                                   underline:underline
                                     reverse:reverse
                                   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(printImage:(UIImage*)image
                  width:(NSInteger)width
                  alignment:(NSInteger)alignment
                  threshold:(NSInteger)threshold
                  ditheringType:(NSInteger)ditheringType
                  compressType:(NSInteger)compressType
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer printImage:image
                                        width:width
                                    alignment:alignment
                                    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(printImageFile:(NSString*)filename
                  width:(NSInteger)width
                  alignment:(NSInteger)alignment
                  threshold:(NSInteger)threshold
                  ditheringType:(NSInteger)ditheringType
                  compressType:(NSInteger)compressType
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer printImageFile:filename
                                            width:width
                                        alignment:alignment
                                        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(printBase64Image:(NSString*)base64String
                  width:(NSInteger)width
                  alignment:(NSInteger)alignment
                  threshold:(NSInteger)threshold
                  ditheringType:(NSInteger)ditheringType
                  compressType:(NSInteger)compressType
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer printBase64Image:base64String
                                              width:width
                                          alignment:alignment
                                          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(printPDFFile:(NSString*)filename
                  width:(NSInteger)width
                  alignment:(NSInteger)alignment
                  startPage:(NSInteger)startPage
                  endPage:(NSInteger)endPage
                  threshold:(NSInteger)threshold
                  ditheringType:(NSInteger)ditheringType
                  compressType:(NSInteger)compressType
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer printPDFFile:filename
                                          width:width
                                      alignment:alignment
                                      startPage:startPage
                                        endPage:endPage
                                      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(print1DBarcode:(NSString*)data
                  symbology:(NSInteger)symbology
                  width:(NSInteger)barWidth
                  height:(NSInteger)height
                  alignment:(NSInteger)alignment
                  textPosition:(NSInteger)textPosition
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer print1DBarcode:data
                                        symbology:symbology
                                            width:barWidth
                                           height:height
                                        alignment:alignment
                                     textPosition:textPosition];
    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(printQRCode:(NSString*)data
                  model:(NSInteger)model
                  alignment:(NSInteger)alignment
                  moduleSize:(NSInteger)moduleSize
                  eccLevel:(NSInteger)eccLevel
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer printQRCode:data
                                         model:model
                                     alignment:alignment
                                    moduleSize:moduleSize
                                      eccLevel:eccLevel];
    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(printPDF417:(NSString*)data
                  symbol:(NSInteger)symbol
                  alignment:(NSInteger)alignment
                  columnNumber:(NSInteger)columnNumber
                  rowNumber:(NSInteger)rowNumber
                  moduleWidth:(NSInteger)moduleWidth
                  moduleHeight:(NSInteger)moduleHeight
                  eccLevel:(NSInteger)eccLevel
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer printPDF417:data
                                        symbol:symbol
                                     alignment:alignment
                                  columnNumber:columnNumber
                                     rowNumber:rowNumber
                                   moduleWidth:moduleWidth
                                  moduleHeight:moduleHeight
                                      eccLevel:eccLevel];
    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(printDataMatrix:(NSString*)data
                  alignment:(NSInteger)alignment
                  moduleSize:(NSInteger)moduleSize
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer printDataMatrix:data alignment:alignment moduleSize:moduleSize];
    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(printLine:(NSInteger)x1
                  y1:(NSInteger)y1
                  x2:(NSInteger)x2
                  y2:(NSInteger)y2
                  thickness:(NSInteger)thickness
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer printLine:x1 y1:y1 x2:x2 y2:y2 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(printBox:(NSInteger)left
                  top:(NSInteger)top
                  right:(NSInteger)right
                  bottom:(NSInteger)bottom
                  thickness:(NSInteger)thickness
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer printBox:left y1:top x2:right y2:bottom 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(printGS1Databar:(NSString*)data
                  symbol:(NSInteger)symbol
                  alignment:(NSInteger)alignment
                  size:(NSInteger)size
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer printGS1Databar:data symbol:symbol alignment:alignment moduleSize:size];
    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(printGS1DatabarMobile:(NSString*)data
                  cData:(NSString*)cData
                  symbol:(NSInteger)symbol
                  alignment:(NSInteger)alignment
                  moduleWidth:(NSInteger)moduleWidth
                  moduleHeight:(NSInteger)moduleHeight
                  segmentHeight:(NSInteger)segmentHeight
                  separatorHeight:(NSInteger)separatorHeight
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer printGS1DatabarMobile:data
                                                   cData:cData
                                                  symbol:symbol
                                               alignment:alignment
                                             moduleWidth:moduleWidth
                                            moduleHeight:(NSInteger)moduleHeight
                                           segmentHeight:segmentHeight
                                         separatorHeight:separatorHeight];
    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(printCompositeSymbology:(NSString*)data
                  cData:(NSString*)cData
                  symbol:(NSInteger)symbol
                  cSymbol:(NSInteger)cSymbol
                  alignment:(NSInteger)alignment
                  size:(NSInteger)size
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer printCompositeSymbology:data
                                                     cData:cData
                                                    symbol:symbol
                                                   cSymbol:cSymbol
                                                 alignment:alignment
                                                      size:size];
    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(printMaxicode:(NSString*)data
                  mode:(NSInteger)mode
                  alignment:(NSInteger)alignment
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer printMaxicode:data mode:mode 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(printAztec:(NSString*)data
                  alignment:(NSInteger)alignment
                  moduleSize:(NSInteger)moduleSize
                  eccLevel:(NSInteger)eccLevel
                  mode:(NSInteger)mode
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer printAztec:data
                                    alignment:alignment
                                   moduleSize:moduleSize
                                     eccLevel:eccLevel
                                         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(checkBattStatus:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    __block NSInteger status = -1;
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    [_printer checkBattStatus:^(NSInteger battStatus) {
        status = battStatus;
        dispatch_semaphore_signal(semaphore);
    }];
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    resolve([NSNumber numberWithInteger:status]);
}

RCT_EXPORT_METHOD(openDrawer:(NSInteger)pinNumber
                  onTimePulse:(NSInteger)onTimePulse
                  offTimePulse:(NSInteger)offTimePulse
                  resolve:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    MPOS_RESULT result = [_printer openDrawer:pinNumber onTimePulse:onTimePulse offTimePulse:offTimePulse];
    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(getModelName:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    resolve([_printer getModelName]);
}

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

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

- (void) statusNotificationHandler:(NSNotification*) notification{
    NSNumber* deviceId = (NSNumber*)[notification object];
    
    if([deviceId integerValue] != [_printer getDeviceId])
        return;
    
    __weak typeof(self) weakSelf = self;
    
    if ([[notification name] isEqualToString: @"StatusUpdateEvent"]){
        RCTLogInfo(@"StatusUpdateEvent");
        
        NSMutableArray *allKeys = [[[notification userInfo] allKeys] mutableCopy];
        for (NSString *key in allKeys) {
            NSInteger status = [[[notification userInfo] objectForKey: key] integerValue];
            status &= ~(128);   // OFFLINE 속성 제거
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                typeof(self) strongSelf = weakSelf;
                if(strongSelf->hasListeners){
                    [strongSelf sendEventWithName:@"StatusUpdateEvent" body:@{
                        @"deviceid":deviceId,
                        @"status":[NSNumber numberWithInteger:status]
                    }];
                }
            });
        }
    }else if ([[notification name] isEqualToString: @"OutputCompletedEvent"]){
        RCTLogInfo(@"OutputCompletedEvent");
        if(hasListeners){
            [self sendEventWithName:@"OutputCompletedEvent" 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:@"PrinterDataEvent" 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
