//
//  ViewController.m
//  btprint
//
//  Created by woosimsystems on 2021/05/13.
//  Copyright © 2021 Woosim Systems. All rights reserved.
//

#import "ViewController.h"
#import "SessionController.h"
#import "woosim302-Swift.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UILabel *rcvDataLabel;
@property (nonatomic, strong) EAAccessory *selectedAccessory;

@end

extern NSString *WSSessionDataReceivedNotification;

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    // watch for the accessory being disconnected
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(accessoryDidDisconnect:)
                                                 name:EAAccessoryDidDisconnectNotification
                                               object:nil];
    // watch for receiving data from the accessory
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(sessionDataReceived:)
                                                 name:WSSessionDataReceivedNotification
                                               object:nil];
    [[EAAccessoryManager sharedAccessoryManager] registerForLocalNotifications];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    [[NSNotificationCenter defaultCenter] removeObserver:self name:EAAccessoryDidDisconnectNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:WSSessionDataReceivedNotification object:nil];
    [[EAAccessoryManager sharedAccessoryManager] unregisterForLocalNotifications];
}

- (void)accessoryDidDisconnect:(NSNotification *)notification
{
    if (_selectedAccessory == nil) {
        return;
    }
    EAAccessory *disconnectedAccessory = [[notification userInfo] objectForKey:EAAccessoryKey];
    if ([disconnectedAccessory connectionID] == [_selectedAccessory connectionID]) {
        self.navigationItem.rightBarButtonItem.title = @"Printer";
        _selectedAccessory = nil;
    }
}

// Data was received from the accessory
- (void)sessionDataReceived:(NSNotification *)notification
{
    NSInteger bytesAvailable = 0;
    NSMutableData *rcvData = [[NSMutableData alloc] init];
    while ((bytesAvailable = [[SessionController sharedController] readBytesAvailable]) > 0) {
        NSData *data = [[SessionController sharedController] readData:bytesAvailable];
        if (data) {
            [rcvData appendData:data];
        }
    }
    WSPacket *packet = [[WSPacket alloc] init:rcvData];
    if ([packet packetType] == PacketTypeMSR) {
        NSArray *tracks = [NSArray arrayWithArray:[packet packetData]];
        NSMutableString *string = [NSMutableString stringWithString:@"MSR Track 1\r\n"];
        [string appendString:[[NSString alloc] initWithData:[tracks objectAtIndex:0] encoding:NSASCIIStringEncoding]];
        [string appendString:@"\r\n\nMSR Track 2\r\n"];
        [string appendString:[[NSString alloc] initWithData:[tracks objectAtIndex:1] encoding:NSASCIIStringEncoding]];
        [string appendString:@"\r\n\nMSR Track 3\r\n"];
        [string appendString:[[NSString alloc] initWithData:[tracks objectAtIndex:2] encoding:NSASCIIStringEncoding]];
        _rcvDataLabel.text = string;
    } else {
        _rcvDataLabel.text = [[NSString alloc] initWithString:[packet packetData]];
    }
}

// right barbutton action
- (IBAction)selectPrinter:(id)sender {
    if (_selectedAccessory) {
        // there is an opened accessory
        [self showOpenedAccessoryAlert];
    } else if ([[[EAAccessoryManager sharedAccessoryManager] connectedAccessories] count] == 0) {
        // no connected accessory
        [self showNoConnectedAccessoryAlert];
    } else {
        // list connected accessories up
        [self showConnectedAccessoriesAlert];
    }
}

- (void)showOpenedAccessoryAlert
{
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Close Session"
                                message:@"Do you want to close session for the accessory?"
                                preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *ok = [UIAlertAction actionWithTitle:@"Yes"
                                                 style:UIAlertActionStyleDefault
                                               handler:^(UIAlertAction *action)
    {
        [[SessionController sharedController] closeSession];
        self.navigationItem.rightBarButtonItem.title = @"Printer";
        self.selectedAccessory = nil;
    }];
    UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"No"
                                                     style:UIAlertActionStyleDefault
                                                   handler:^(UIAlertAction *action)
    {
        [alert dismissViewControllerAnimated:YES completion:nil];
    }];
    [alert addAction:ok];
    [alert addAction:cancel];
    [self presentViewController:alert animated:YES completion:nil];
}

- (void)showNoConnectedAccessoryAlert
{
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"No Accessory Connected"
                                message:@"Do you want to move to Settings?"
                                preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *ok = [UIAlertAction actionWithTitle:@"Yes"
                                                 style:UIAlertActionStyleDefault
                                               handler:^(UIAlertAction *action)
    {
        [alert dismissViewControllerAnimated:YES completion:nil];
        NSURL *URL = [NSURL URLWithString:@"App-prefs:root=Bluetooth"];
        [[UIApplication sharedApplication] openURL:URL options:@{} completionHandler:nil];
    }];
    UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"No"
                                                     style:UIAlertActionStyleDefault
                                                   handler:^(UIAlertAction *action)
    {
        [alert dismissViewControllerAnimated:YES completion:nil];
    }];
    [alert addAction:ok];
    [alert addAction:cancel];
    [self presentViewController:alert animated:YES completion:nil];
}

- (void)showConnectedAccessoriesAlert
{
    NSArray *supportedProtocolsStrings = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UISupportedExternalAccessoryProtocols"];
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Select Printer"
                                                                   message:nil
                                                            preferredStyle:UIAlertControllerStyleActionSheet];
    // add accessoryList item
    for (EAAccessory *accessory in [[EAAccessoryManager sharedAccessoryManager] connectedAccessories]) {
        UIAlertAction *select = [UIAlertAction actionWithTitle:[accessory modelNumber]
                                                         style:UIAlertActionStyleDefault
                                                       handler:^(UIAlertAction *action)
        {
            for (NSString *supportedProtocolsString in supportedProtocolsStrings) {
                for (NSString *protocolString in [accessory protocolStrings]) {
                    // session open if there is the same protocol string
                    if ([protocolString isEqualToString:supportedProtocolsString]) {
                        self.selectedAccessory = accessory;
                        if ([[SessionController sharedController] openSessionForAccessory:accessory withProtocolString:protocolString]) {
                            self.navigationItem.rightBarButtonItem.title = [accessory modelNumber];
                        }
                        return;
                    }
                }
            }
            // alert that there is no same protocol string
            UIAlertController *protocolStringAlert = [UIAlertController alertControllerWithTitle:@"Protocol String Error"
                   message:@"Selected accessory does not support assigned protocol string"
                   preferredStyle:UIAlertControllerStyleAlert];
            [self presentViewController:protocolStringAlert animated:YES completion:nil];
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2*NSEC_PER_SEC), dispatch_get_main_queue(), ^{
                [protocolStringAlert dismissViewControllerAnimated:YES completion:nil];
            });
        }];
        [alert addAction:select];
    }
    UIAlertAction *moveSettings = [UIAlertAction actionWithTitle:@"Other printer"
                                                           style:UIAlertActionStyleDefault
                                                         handler:^(UIAlertAction *action)
    {
        [alert dismissViewControllerAnimated:YES completion:nil];
        NSURL *URL = [NSURL URLWithString:@"App-prefs:root=Bluetooth"];
        [[UIApplication sharedApplication] openURL:URL options:@{} completionHandler:nil];
    }];
    UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel"
                                                     style:UIAlertActionStyleDefault
                                                   handler:^(UIAlertAction *action)
    {
        [alert dismissViewControllerAnimated:YES completion:nil];
    }];
    [alert addAction:moveSettings];
    [alert addAction:cancel];
    alert.popoverPresentationController.barButtonItem = self.navigationItem.rightBarButtonItem;
    [self presentViewController:alert animated:YES completion:nil];
}

- (IBAction)printText:(id)sender {
    NSMutableData *data = [[NSMutableData alloc]init];
    [data appendData:[WSCmd initPrinter]];
    [data appendData:[WSCmd alignContent:AlignTypeRight]];
    UIImage *logo = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"logo" ofType:@"jpg"]];
    [data appendData:[WSImage printImage:logo dithering:NO compress:NO]];
    [data appendData:[WSCmd alignText:AlignTypeCenter]];
    [data appendData:[WSCmd extendFontWithWidth:2 height:2]];
    [data appendData:[@"Receipt" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd alignText:AlignTypeLeft]];
    [data appendData:[WSCmd extendFontWithWidth:1 height:1]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"NAME" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd alignText:AlignTypeRight]];
    [data appendData:[@"Woosim Coffee\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd alignText:AlignTypeLeft]];
    [data appendData:[@"MASTER" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd alignText:AlignTypeRight]];
    [data appendData:[@"Gil-dong Hong\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd alignText:AlignTypeLeft]];
    [data appendData:[@"ADDRESS" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd alignText:AlignTypeRight]];
    [data appendData:[@"#60, Sandan-ro\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[@"388beon-gil, Galsan-myeon\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[@"Hongseong-gun, Chungnam-do\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[@"Republic of Korea\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd alignText:AlignTypeLeft]];
    [data appendData:[@"HELP DESK" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd alignText:AlignTypeRight]];
    [data appendData:[WSCmd setBold:YES]];
    [data appendData:[WSCmd setReverse:YES]];
    [data appendData:[@"+82-41-339-3700\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd alignText:AlignTypeLeft]];
    [data appendData:[WSCmd setBold:NO]];
    [data appendData:[WSCmd setReverse:NO]];
    [data appendData:[@"--------------------------------\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[@"Cafe Mocha          2       4.50\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[@"Cafe Latte          1       4.00\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[@"Cappucino           1       4.00\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[@"--------------------------------\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd setBold:YES]];
    [data appendData:[@"Total                     $17.00\n\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd setBold:NO]];
    [data appendData:[WSCmd alignContent:AlignTypeCenter]];
    [data appendData:[WSCmd setBarcodeWidth:2]];
    [data appendData:[WSCmd setBarcodeHeight:60]];
    [data appendData:[WSCmd setBarcodeHri:YES]];
    [data appendData:[WSCmd writeBarcode:@"051320211323+0900" type:BarcodeTypeCode128]];
    [data appendData:[WSCmd printFeedWithLine:3]];
    [data appendData:[@"Hello\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd setCodeTable:CharsetCP860 mcu:McuTypeRX]];
    [data appendData:[@"Olá\n" dataUsingEncoding:CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingDOSPortuguese)]];
    [data appendData:[WSCmd setCodeTable:CharsetCP737 mcu:McuTypeRX]];
    [data appendData:[@"γεια\n" dataUsingEncoding:CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingDOSGreek)]];
    [data appendData:[WSCmd setCodeTable:CharsetCP866 mcu:McuTypeRX]];
    [data appendData:[@"Привет\n" dataUsingEncoding:CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingDOSRussian)]];
    // Korean is only working property with Korean version FW
    [data appendData:[WSCmd setCodeTable:CharsetDBCS mcu:McuTypeRX]];
    [data appendData:[@"안녕하세요\n" dataUsingEncoding:CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingEUC_KR)]];
    [data appendData:[WSCmd printFeedWithLine:3]];
    [[SessionController sharedController] writeData:data];
}

- (IBAction)printImage:(id)sender {
    NSMutableData *data = [[NSMutableData alloc]init];
    [data appendData:[WSCmd initPrinter]];
    [data appendData:[WSCmd setPageMode]];
    [data appendData:[WSCmd pageModeSetAreaWithX:0 y:0 width:384 height:400]];
    [data appendData:[WSImage drawRectWithX:0 y:0 width:384 height:395 thick:5]];
    [data appendData:[WSImage drawLineWithX1:20 y1:0 x2:20 y2:395 thick:3]];
    [data appendData:[WSImage drawLineWithX1:364 y1:0 x2:364 y2:395 thick:3]];
    [data appendData:[WSImage drawLineWithX1:0 y1:20 x2:384 y2:20 thick:3]];
    [data appendData:[WSImage drawLineWithX1:0 y1:375 x2:384 y2:375 thick:3]];
    [data appendData:[WSImage drawEllipseWithX:192 y:200 radiusW:160 radiusH:160 thick:4]];
    UIImage *image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"logo" ofType:@"jpg"]];
    [data appendData:[WSImage drawImage:image x:118 y:62 dithering:YES compress:NO]];
    UIImage *image2 = [WSImage adjustImage:image brightness:-0.3 contrast:2.0];
    [data appendData:[WSImage drawImage:image2 x:118 y:162 dithering:YES compress:NO]];
    [data appendData:[WSImage drawImage:image x:118 y:262 dithering:NO compress:NO]];
    [data appendData:[WSCmd pageModePrintStdMode]];
    [data appendData:[WSCmd printData]];
    UIImage *logo = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"logo" ofType:@"bmp"]];
    [data appendData:[WSImage printImage:logo dithering:NO compress:YES]];
    [data appendData:[WSCmd printFeedWithLine:3]];
    [[SessionController sharedController] writeData:data];
}

- (IBAction)print1DBarcode:(id)sender {
    NSMutableData *data = [[NSMutableData alloc]init];
    [data appendData:[WSCmd initPrinter]];
    [data appendData:[WSCmd setBarcodeWidth:2]];
    [data appendData:[WSCmd setBarcodeHeight:60]];
    [data appendData:[WSCmd setBarcodeHri:YES]];
    [data appendData:[@"UPC-A\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeBarcode:@"01234567890" type:BarcodeTypeUPCA]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"UPC-E\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeBarcode:@"065100004327" type:BarcodeTypeUPCE]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"EAN13\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeBarcode:@"0123456789012" type:BarcodeTypeEAN13]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"EAN8\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeBarcode:@"01234567" type:BarcodeTypeEAN8]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"Code39\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeBarcode:@"01234567890" type:BarcodeTypeCode39]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"ITF\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeBarcode:@"01234567890" type:BarcodeTypeITF]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"Codabar\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeBarcode:@"01234567890" type:BarcodeTypeCodabar]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"Code93\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeBarcode:@"01234567890" type:BarcodeTypeCode93]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"Code128\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeBarcode:@"01234567890" type:BarcodeTypeCode128]];
    [data appendData:[WSCmd printFeedWithLine:3]];
    [[SessionController sharedController] writeData:data];
}

- (IBAction)print2DBarcode:(id)sender {
    NSMutableData *data = [[NSMutableData alloc]init];
    [data appendData:[WSCmd initPrinter]];
    [data appendData:[WSCmd setBarcodeWidth:2]];
    [data appendData:[WSCmd setBarcodeHri:NO]];
    [data appendData:[@"PDF417\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writePDF417:[@"http://www.woosim.com/" dataUsingEncoding:NSASCIIStringEncoding] column:3 secureLevel:4 ratio:2]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"DataMatrix\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeDataMatrix:[@"http://www.woosim.com/" dataUsingEncoding:NSASCIIStringEncoding] height:0 width:0 size:6]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"QR Code\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeQRcode:[@"http://www.woosim.com/" dataUsingEncoding:NSASCIIStringEncoding] version:0 ecLevel:@"M" size:5]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"Micro PDF417\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeMicroPDF417:[@"http://www.woosim.com/" dataUsingEncoding:NSASCIIStringEncoding] column:2 row:0 ratio:2]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"Truncated PDF417\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeTruncatedPDF417:[@"http://www.woosim.com/" dataUsingEncoding:NSASCIIStringEncoding] column:3 secureLevel:4 ratio:2]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"Maxicode\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeMaxicode:[@"ABCDE12345abcde" dataUsingEncoding:NSASCIIStringEncoding] mode:4]];
    [data appendData:[WSCmd printFeedWithLine:3]];
    [[SessionController sharedController] writeData:data];
}

- (IBAction)printGS1Databar:(id)sender {
    NSMutableData *data = [[NSMutableData alloc]init];
    [data appendData:[WSCmd initPrinter]];
    [data appendData:[@"GS1 Databar Omnidirectional\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeGS1Databar:@"0001234567890" type:GS1DatabarTypeOmnidirectional segment:2]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"GS1 Databar Truncated\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeGS1Databar:@"0001234567890" type:GS1DatabarTypeTruncated segment:2]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"GS1 Databar Stacked\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeGS1Databar:@"0001234567890" type:GS1DatabarTypeStacked segment:2]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"GS1 Databar Stacked Omnidirectional\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeGS1Databar:@"0001234567890" type:GS1DatabarTypeStackedOmnidirectional segment:2]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"GS1 Databar Limited\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeGS1Databar:@"0001234567890" type:GS1DatabarTypeLimited segment:2]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"GS1 Databar Expanded\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeGS1Databar:@"[01]90012345678908[3103]012233" type:GS1DatabarTypeExpanded segment:2]];
    [data appendData:[WSCmd printData]];
    [data appendData:[@"GS1 Databar Expanded Stacked\n" dataUsingEncoding:NSASCIIStringEncoding]];
    [data appendData:[WSCmd writeGS1Databar:@"[01]90012345678908[3103]012233[15]991231" type:GS1DatabarTypeExpandedStacked segment:4]];
    [data appendData:[WSCmd printFeedWithLine:3]];
    [[SessionController sharedController] writeData:data];
}

- (IBAction)setMsrMode:(id)sender {
    _rcvDataLabel.text = @"";
    [[SessionController sharedController] writeData:[WSCmd setMsrModeTripleTrack]];
}

- (IBAction)cancelMsrMode:(id)sender {
    [[SessionController sharedController] writeData:[WSCmd exitMsrMode]];
}

- (IBAction)getDeviceName:(id)sender {
    _rcvDataLabel.text = @"";
    [[SessionController sharedController] writeData:[WSCmd requestDeviceName]];
}

- (IBAction)getStatus:(id)sender {
    _rcvDataLabel.text = @"";
    [[SessionController sharedController] writeData:[WSCmd requestStatus]];
}

@end
