#import "RNGPrinterLegacy.h"
// #import "PrinterSDK.h"
// #import "TscCommand.h"
// #import "ConnecterManager.h"
#import <React/RCTLog.h>
#import "EthernetConnecter.h"
#import "TscCommand.h"
// #import "ConnecterManager.h"

@implementation RNGPrinterLegacy

- (dispatch_queue_t)methodQueue
{
    return dispatch_get_main_queue();
}

RCT_EXPORT_MODULE()

RCT_EXPORT_METHOD(init:(RCTResponseSenderBlock)successCallback
                  fail:(RCTResponseSenderBlock)errorCallback) {
    connected_ip = nil;
    is_scanning = NO;
    _printerArray = [NSMutableArray new];
    connecter = [[EthernetConnecter alloc] init];
    successCallback(@[@"Init successful"]);
}

RCT_EXPORT_METHOD(connectIP:(NSString *)ip
                  withPort:(nonnull NSNumber *)port
                  success:(RCTResponseSenderBlock)successCallback
                  fail:(RCTResponseSenderBlock)errorCallback) {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        @try {
            if (connecter == nil) {
                connecter = [[EthernetConnecter alloc] init];
            }
            
            [connecter connectIP:ip port:[port intValue] connectState:^(ConnectState state) {
                NSString *stateMessage;
                switch (state) {
                    case CONNECT_STATE_CONNECTED: {
                        stateMessage = @"CONNECTED";
                        connected_ip = ip;
                        dispatch_async(dispatch_get_main_queue(), ^{
                            successCallback(@[stateMessage, [NSString stringWithFormat:@"Connecting to printer %@", ip]]);
                        });
                        break;
                    }
                    case CONNECT_STATE_DISCONNECT: {
                        stateMessage = @"DISCONNECTED";
                        dispatch_async(dispatch_get_main_queue(), ^{
                            errorCallback(@[stateMessage, [NSString stringWithFormat:@"Printer %@ disconnected", ip]]);
                        });
                        break;
                    }
                    case CONNECT_STATE_CONNECTING: {
                        stateMessage = @"CONNECTING";
                        dispatch_async(dispatch_get_main_queue(), ^{
                            errorCallback(@[stateMessage, [NSString stringWithFormat:@"Connecting to printer %@", ip]]);
                        });
                        break;
                    }
                    case CONNECT_STATE_TIMEOUT: {
                        stateMessage = @"TIMEOUT";
                        dispatch_async(dispatch_get_main_queue(), ^{
                            errorCallback(@[stateMessage, [NSString stringWithFormat:@"Connection to printer %@ timed out", ip]]);
                        });
                        break;
                    }
                    case CONNECT_STATE_FAILT: {
                        stateMessage = @"FAILED";
                        dispatch_async(dispatch_get_main_queue(), ^{
                            errorCallback(@[stateMessage, [NSString stringWithFormat:@"Failed to connect to printer %@", ip]]);
                        });
                        break;
                    }
                    case NOT_FOUND_DEVICE: {
                        stateMessage = @"NOT_FOUND";
                        dispatch_async(dispatch_get_main_queue(), ^{
                            errorCallback(@[stateMessage, [NSString stringWithFormat:@"Printer %@ not found", ip]]);
                        });
                        break;
                    }
                    default: {
                        stateMessage = @"UNKNOWN";
                        dispatch_async(dispatch_get_main_queue(), ^{
                            errorCallback(@[stateMessage, [NSString stringWithFormat:@"Unknown state for printer %@", ip]]);
                        });
                        break;
                    }
                }
            }];
        } @catch (NSException *exception) {
            dispatch_async(dispatch_get_main_queue(), ^{
                errorCallback(@[@"ERROR", exception.reason]);
            });
        }
    });
}

RCT_EXPORT_METHOD(addStrToCommand:(NSString *)str
                  success:(RCTResponseSenderBlock)successCallback
                  fail:(RCTResponseSenderBlock)errorCallback) {
    @try {
        !connected_ip ? [NSException raise:@"Invalid connection" format:@"Can't connect to printer"] : nil;
        
        TscCommand *command = [[TscCommand alloc] init];
        [command addStrToCommand:str];
        NSData *data = [command getCommand];
        
        [connecter write:data];
        successCallback(@[@"Command sent successfully"]);
    } @catch (NSException *exception) {
        errorCallback(@[exception.reason]);
    }
}

RCT_EXPORT_METHOD(addNSDataToCommand:(NSString *)base64Data
                  success:(RCTResponseSenderBlock)successCallback
                  fail:(RCTResponseSenderBlock)errorCallback) {
    @try {
        !connected_ip ? [NSException raise:@"Invalid connection" format:@"Can't connect to printer"] : nil;
        
        NSData *data = [[NSData alloc] initWithBase64EncodedString:base64Data options:0];
        if (!data) {
            [NSException raise:@"Invalid data" format:@"Invalid base64 data"];
        }
        
        TscCommand *command = [[TscCommand alloc] init];
        [command addNSDataToCommand:data];
        NSData *commandData = [command getCommand];
        
        [connecter write:commandData];
        successCallback(@[@"Data sent successfully"]);
    } @catch (NSException *exception) {
        errorCallback(@[exception.reason]);
    }
}

RCT_EXPORT_METHOD(addPrint:(nonnull NSNumber *)m
                  withN:(nonnull NSNumber *)n
                  success:(RCTResponseSenderBlock)successCallback
                  fail:(RCTResponseSenderBlock)errorCallback) {
    @try {
        !connected_ip ? [NSException raise:@"Invalid connection" format:@"Can't connect to printer"] : nil;
        
        TscCommand *command = [[TscCommand alloc] init];
        [command addPrint:[m intValue] :[n intValue]];
        NSData *data = [command getCommand];
        
        [connecter write:data];
        successCallback(@[@"Print command sent successfully"]);
    } @catch (NSException *exception) {
        errorCallback(@[exception.reason]);
    }
}

RCT_EXPORT_METHOD(addCls:(RCTResponseSenderBlock)successCallback
                  fail:(RCTResponseSenderBlock)errorCallback) {
    @try {
        !connected_ip ? [NSException raise:@"Invalid connection" format:@"Can't connect to printer"] : nil;
        
        TscCommand *command = [[TscCommand alloc] init];
        [command addCls];
        NSData *data = [command getCommand];
        
        [connecter write:data];
        successCallback(@[@"Clear command sent successfully"]);
    } @catch (NSException *exception) {
        errorCallback(@[exception.reason]);
    }
}

RCT_EXPORT_METHOD(closeConn) {
    @try {
        [connecter close];
        connected_ip = nil;
    } @catch (NSException *exception) {
        NSLog(@"%@", exception.reason);
    }
}

RCT_EXPORT_METHOD(close:(RCTResponseSenderBlock)successCallback
                  fail:(RCTResponseSenderBlock)errorCallback) {
    @try {
        [connecter close];
        connected_ip = nil;
        successCallback(@[@"Connection closed successfully"]);
    } @catch (NSException *exception) {
        errorCallback(@[exception.reason]);
    }
}

@end 