//
//  ViewController.m
//  SiiLibSample
//

#import <SIIPrinterManager/SIIPrinterManager.h>
#import <ExternalAccessory/ExternalAccessory.h>
#import "UniformTypeIdentifiers/UniformTypeIdentifiers.h"
#import "ViewController.h"
#import "PrinterListViewController.h"
#import "SettingsViewController.h"
#import "SampleFunctions.h"
#import "SampleValue.h"
#import "SiiPrinter.h"
#import "DisplayData.h"

@interface ViewController () <UIDocumentPickerDelegate, SIIPrinterManagerDelegate> {
    IBOutlet UITextField *_addressText;
    IBOutlet UIButton *_printerModel;
    IBOutlet UISwitch *_isStatusEnable;
    IBOutlet UITextField *_printerStatus;
    IBOutlet UITextField *_barcodeStatus;
    IBOutlet UISwitch *_isBarcodeEncode;
    IBOutlet UITextField *_barcodeData;
    IBOutlet UILabel *_versionLabel;
    dispatch_queue_t _gcd_printerManagerQueue;
}

@property (weak, nonatomic) IBOutlet UIView *loadingView;
@property (strong, nonatomic) SiiPrinter* printer;

@end

@implementation ViewController

+ (void) initialize {
    [super initialize];
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    NSMutableDictionary *appDefaults = [NSMutableDictionary dictionary];
    [appDefaults setObject:VALUE_PRINTER_ADDRESS forKey:KEY_PRINTER_ADDRESS];
    [appDefaults setObject:VALUE_PRINTER_PORT_TYPE forKey:KEY_PRINTER_PORT_TYPE];
    [appDefaults setObject:VALUE_PRINTER_MODELNAME forKey:KEY_PRINTER_MODELNAME];
    [appDefaults setObject:VALUE_TEXTFIELD_ADDRESS forKey:KEY_TEXTFIELD_ADDRESS];
    [userDefaults registerDefaults:appDefaults];
    [self createSampleFile];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [SampleFunctions InitialSetting];
    [SampleFunctions setDelegate:self];
    self.loadingView.hidden = YES;
    _gcd_printerManagerQueue = dispatch_queue_create("com.sii-ps.printerManager", DISPATCH_QUEUE_SERIAL);
    
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    NSString *address  = [userDefaults stringForKey:KEY_PRINTER_ADDRESS];
    NSString *modelName = [userDefaults stringForKey:KEY_PRINTER_MODELNAME];
    NSString *portType = [userDefaults stringForKey:KEY_PRINTER_PORT_TYPE];
    self.printer = [[SiiPrinter alloc] initWithPrinterInformation:address modelName:modelName portType:portType];
    _addressText.text = [userDefaults stringForKey:KEY_TEXTFIELD_ADDRESS];
    [_printerModel setTitle:[userDefaults stringForKey:KEY_PRINTER_MODELNAME] forState:UIControlStateNormal];
    _versionLabel.text = [NSString stringWithFormat:@"SDK Version: %@", [SampleFunctions getVersionSample]];
}

- (IBAction)onPrinterModelTouched:(id)sender {
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:@"Select printer model" preferredStyle:UIAlertControllerStyleAlert];
    NSArray *modelList = @[
        PRINTER_MODEL_NAME_RPD10,
        PRINTER_MODEL_NAME_RPE10,
        PRINTER_MODEL_NAME_RPF10,
        PRINTER_MODEL_NAME_DPUS245,
        PRINTER_MODEL_NAME_DPUS445,
        PRINTER_MODEL_NAME_MPB20,
        PRINTER_MODEL_NAME_MPB21L,
        PRINTER_MODEL_NAME_MPB30,
        PRINTER_MODEL_NAME_MPB30L,
        PRINTER_MODEL_NAME_SLP720RT,
        PRINTER_MODEL_NAME_MPA40];
    for (int i=0; i<modelList.count; i++) {
        NSString *modelName = [modelList objectAtIndex:i];
        [alertController addAction:[UIAlertAction actionWithTitle:modelName style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
            [self->_printerModel setTitle:modelName forState:UIControlStateNormal];
            [self saveDefault:modelName key:KEY_PRINTER_MODELNAME];
            self.printer.modelName = modelName;
            self.printer.model = [self.printer getPrinterModel:modelName];
        }]];
    }
    [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
    }]];
    [self presentViewController:alertController animated:YES completion:nil];
}

- (IBAction)onConnectButtonTouched:(id)sender {
    [self showLoadingView];
    dispatch_async(_gcd_printerManagerQueue, ^{
        [SampleFunctions connectSample:self.printer.model address:self.printer.address type:self.printer.type];
        [self hideLoadingView];
        [self showResult:[SampleFunctions getResultMessage]];
    });
}

- (IBAction)onDisconnectButtonTouched:(id)sender {
    [self showLoadingView];
    dispatch_async(_gcd_printerManagerQueue, ^{
        [SampleFunctions disconnectSample];
        [self resetStatus];
        [self hideLoadingView];
        [self showResult:[SampleFunctions getResultMessage]];
    });
}

- (IBAction)onStandardModeSampleButtonTouched:(id)sender {
    [self showLoadingView];
    dispatch_async(_gcd_printerManagerQueue, ^{
        [SampleFunctions standardModeSample];
        [self hideLoadingView];
        [self showResult:[SampleFunctions getResultMessage]];
    });
}

- (IBAction)onPageModeSampleButtonTouched:(id)sender {
    [self showLoadingView];
    dispatch_async(_gcd_printerManagerQueue, ^{
        [SampleFunctions printPageModeSample];
        [self hideLoadingView];
        [self showResult:[SampleFunctions getResultMessage]];
    });
}

- (IBAction)onSmartLabelSampleButtonTouched:(id)sender {
    [self showLoadingView];
    dispatch_async(_gcd_printerManagerQueue, ^{
        [SampleFunctions smartLabelSample];
        [self hideLoadingView];
        [self showResult:[SampleFunctions getResultMessage]];
    });
}

- (IBAction)onDisplaySampleButtonTouched:(id)sender {
    [self showLoadingView];
    dispatch_async(_gcd_printerManagerQueue, ^{
        [SampleFunctions displaySample];
        [self hideLoadingView];
        [self showResult:[SampleFunctions getResultMessage]];
    });
}

- (IBAction)onSendDataFileButtonTouched:(id)sender {
    // The sendDataFile function allows following file extensions:
    // .bmp, .jpg/.jpeg, .png, .txt, .bin, .dat, .htm/.html
    NSArray<UTType*> *types = @[
        [UTType typeWithFilenameExtension:@"bmp"],
        [UTType typeWithFilenameExtension:@"jpg"],
        [UTType typeWithFilenameExtension:@"jpeg"],
        [UTType typeWithFilenameExtension:@"png"],
        [UTType typeWithFilenameExtension:@"txt"],
        [UTType typeWithFilenameExtension:@"bin"],
        [UTType typeWithFilenameExtension:@"dat"],
        [UTType typeWithFilenameExtension:@"html"],
        [UTType typeWithFilenameExtension:@"htm"],
    ];
    // show a document picker
    UIDocumentPickerViewController *documentPicker =
    [[UIDocumentPickerViewController alloc] initForOpeningContentTypes:types];
    documentPicker.delegate = self;
    documentPicker.modalPresentationStyle = UIModalPresentationFormSheet;
    documentPicker.view.tag = 1;
    [self presentViewController:documentPicker animated:YES completion:nil];
}

- (IBAction)onPrintPDFButtonTouched:(id)sender {
    // The printPDF function allows following file extension:
    // .pdf
    NSArray<UTType*> *types = @[
        [UTType typeWithFilenameExtension:@"pdf"],
    ];
    // show a document picker
    UIDocumentPickerViewController *documentPicker =
    [[UIDocumentPickerViewController alloc] initForOpeningContentTypes:types];
    documentPicker.delegate = self;
    documentPicker.modalPresentationStyle = UIModalPresentationFormSheet;
    documentPicker.view.tag = 2;
    [self presentViewController:documentPicker animated:YES completion:nil];
}

- (IBAction)onOpenDrawerButtonTouched:(id)sender {
    [self showLoadingView];
    dispatch_async(_gcd_printerManagerQueue, ^{
        [SampleFunctions openDrawerSample];
        [self hideLoadingView];
        [self showResult:[SampleFunctions getResultMessage]];
    });
}

- (IBAction)isStatusEnableChanged:(id)sender {
    if (self->_isStatusEnable.isOn == YES) {
        [SampleFunctions setDelegate:self];
    } else {
        [SampleFunctions disableDelegate];
        [self resetStatus];
    }
}

/// Segue back from printer list View
- (IBAction)firstViewReturnActionForSegue:(UIStoryboardSegue *)segue {
    PrinterListViewController *printerListView = segue.sourceViewController;
    // Get selected printer from printer list view
    self.printer = printerListView.printer;
    NSString *str = [NSString stringWithFormat:@"%@(%@)", self.printer.address, self.printer.portType];
    _addressText.text = str;
    [_printerModel setTitle:self.printer.modelName forState:UIControlStateNormal];
    // Set user default
    [self saveDefault:str key:KEY_TEXTFIELD_ADDRESS];
    [self saveDefault:self.printer.address key:KEY_PRINTER_ADDRESS];
    [self saveDefault:self.printer.modelName key:KEY_PRINTER_MODELNAME];
    [self saveDefault:self.printer.portType key:KEY_PRINTER_PORT_TYPE];
}

- (void)showLoadingView {
    dispatch_async(dispatch_get_main_queue(), ^{
        self->_loadingView.hidden = NO;
    });
}

- (void)hideLoadingView {
    dispatch_async(dispatch_get_main_queue(), ^{
        self->_loadingView.hidden = YES;
    });
}

- (void)showResult:(NSString *)resultText {
    dispatch_async(dispatch_get_main_queue(), ^{
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:resultText preferredStyle:UIAlertControllerStyleAlert];
        [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        }]];
        [self presentViewController:alertController animated:YES completion:nil];
    });
}

- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls {
    [self showLoadingView];
    NSInteger tag = controller.view.tag;
    dispatch_async(_gcd_printerManagerQueue, ^{
        // When a file is picked
        NSURL *file = urls.firstObject;
        NSString *result = @"";
        @try {
            // Get selected file's path from url
            NSString *filePath = [file path];
            if ([file startAccessingSecurityScopedResource] == YES) {
                // Send file path to printer
                if (tag == 1){
                    [SampleFunctions sendDataFileSample:filePath];
                } else if (tag == 2){
                    [SampleFunctions printPDFSample:filePath];
                }
                result = [SampleFunctions getResultMessage];
                [file stopAccessingSecurityScopedResource];
            }
        } @catch (NSException *exception) {
            result = exception.description;
        } @finally {
            [self hideLoadingView];
            [self showResult:result];
        }
    });
}

/// Implementation delegate function defined in SIIPrinterManagerDelegate
- (void)didStatusChange:(SIIPrinterManager *)printerManager status:(NSInteger)status {
    dispatch_async(dispatch_get_main_queue(), ^{
        self->_printerStatus.text = [NSString stringWithFormat:@"0x%02lX\n", (long)status];
    });
}

/// Implementation delegate function defined in SIIPrinterManagerDelegate
- (void)didBarcodeScannerReadData:(SIIPrinterManager *)printerManager data:(NSData *)data {
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self->_isBarcodeEncode.isOn) {
            NSString *endodedString = [[NSString alloc] initWithData:data encoding:NSShiftJISStringEncoding];
            if (endodedString) {
                self->_barcodeData.text = endodedString;
            } else {
                self->_barcodeData.text = @"Encoding failed!!";
            }
        } else {
            UInt8 buf[data.length];
            [data getBytes:buf length:data.length];
            NSMutableString *str = [NSMutableString stringWithCapacity:10];
            for (int i = 0; i < data.length; i++) {
                [str appendString:[NSString stringWithFormat:@"%02lX", (long)buf[i]]];
            }
            self->_barcodeData.text = str;
        }
    });
}

/// Implementation delegate function defined in SIIPrinterManagerDelegate
- (void)didBarcodeScannerChangedOnline:(SIIPrinterManager *)printerManager {
    dispatch_async(dispatch_get_main_queue(), ^{
        self->_barcodeStatus.text = @"Online";
    });
}

/// Implementation delegate function defined in SIIPrinterManagerDelegate
- (void)didBarcodeScannerChangedOffline:(SIIPrinterManager *)printerManager {
    dispatch_async(dispatch_get_main_queue(), ^{
        self->_barcodeStatus.text = @"Offline";
    });
}

- (void)resetStatus {
    dispatch_async(dispatch_get_main_queue(), ^{
        self->_printerStatus.text = @"";
        self->_barcodeData.text = @"";
        self->_barcodeStatus.text  = @"";
    });
}

- (void)saveDefault:(id)object key:(NSString *)key {
    NSUserDefaults *myDefaults = [NSUserDefaults standardUserDefaults];
    [myDefaults setObject:object forKey:key];
    [myDefaults synchronize];
}

+ (void)createSampleFile {
    NSString *documentsDirectoryPath = [NSString stringWithFormat:@"%@/Documents/", NSHomeDirectory()];
    NSString *filePath = [NSString stringWithFormat:@"%@Sample.txt", documentsDirectoryPath];
    BOOL result = [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
    if (result == YES) {
        NSString *text = @"SampleText\n";
        [text writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
    }
}
@end
