//
//  PrinterListViewController.m
//  SIIMpaPrinterSample
//

#import "PrinterListViewController.h"
#import <SIIMpaPrinterManager/SIIMpaPrinterManager.h>
#import <ExternalAccessory/ExternalAccessory.h>
#import "PrinterManager.h"
#import "ValueManager.h"

@interface PrinterListViewController ()<UITableViewDelegate, UITableViewDataSource>
@property (strong, nonatomic) IBOutlet UITableView *tableView;
@property (strong, nonatomic) IBOutlet UIView *printerListLoadingView;

@end

@implementation PrinterListViewController {
    NSArray *_tableData;
    dispatch_queue_t _gcd_printerDiscoverQueue;
    BOOL _discoverComplete;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.tableView.delegate = (id <UITableViewDelegate>)self;
    self.tableView.dataSource = (id <UITableViewDataSource>)self;
    _gcd_printerDiscoverQueue = dispatch_queue_create("com.sii-ps.mpaPrinterDiscover", DISPATCH_QUEUE_SERIAL);
    self.printer = [[SiiPrinter alloc] init];
}

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

- (void)viewDidAppear:(BOOL)animated {
    [self searchPrinter];
}

- (IBAction)onRefreshPrinterListButtonTouched:(id)sender {
    _tableData = nil;
    [self searchPrinter];
}

- (IBAction)onClosePrinterListViewButtonTouched:(id)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (IBAction)onLoadingViewCancelButtonTouched:(id)sender {
    [self hidePrinterListLoadingView];
    [PrinterManager cancelDiscoveryTcpPrinter];
}

- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"PrinterListViewCell";
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    SIIMpaDiscoveredPrinter *printer = [_tableData objectAtIndex:indexPath.row];
    if (printer.ipAddress.length != 0) {
        cell.textLabel.text = [NSString stringWithFormat:@"%@", printer.ipAddress];
        cell.detailTextLabel.text = [NSString stringWithFormat:@"%@  %@",  PORTTYPE_TCP_IP, printer.printerModel];
    } else if (printer.bluetoothAddress.length != 0) {
        cell.textLabel.text = [NSString stringWithFormat:@"%@", printer.bluetoothAddress];
        cell.detailTextLabel.text = [NSString stringWithFormat:@"%@  %@",  PORTTYPE_BLUETOOTH, printer.printerModel];
    }
    cell.accessoryType = UITableViewCellAccessoryNone;
    return cell;
}

- (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return _tableData.count;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    SIIMpaDiscoveredPrinter *discoveredPrinter = _tableData[indexPath.row];
    if (discoveredPrinter.ipAddress.length != 0) {
        self.printer.portType = PORTTYPE_TCP_IP;
        self.printer.address = discoveredPrinter.ipAddress;
    } else if (discoveredPrinter.bluetoothAddress.length != 0) {
        self.printer.portType = PORTTYPE_BLUETOOTH;
        self.printer.address = discoveredPrinter.bluetoothAddress;
    }
    self.printer.modelName = discoveredPrinter.printerModel;
    // Back to main view
    [self performSegueWithIdentifier:@"return" sender:self];
}

/// Printer discovery process
- (void)searchPrinter {
    [self showPrinterListLoadingView];
    dispatch_async(_gcd_printerDiscoverQueue, ^{
        [self searchBluetoothPrinter];
        [self searchTcpPrinter];
        [self hidePrinterListLoadingView];
    });
}

/// Bluetooth printer discovery process
- (void)searchBluetoothPrinter {
    NSMutableArray *printerList = [[NSMutableArray alloc] init];
    // Get accessories that connecting with current iOS device from EAAccessoryManager
    
    NSArray *btPrinter = [PrinterManager getBluetoothPrinterList];
    if (btPrinter.count > 0) {
        for (int i = 0; i < btPrinter.count; i++) {
            [printerList addObject:[btPrinter objectAtIndex:i]];
        }
    }
    self->_tableData = printerList;
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.tableView reloadData];
    });
}

/// Tcp printer discovery process
- (void)searchTcpPrinter {
    NSMutableArray *printerList = [[NSMutableArray alloc] init];
    [PrinterManager startDiscoveryTcpPrinter];
    
    // Repeat process until discovery completed
    while (![PrinterManager discoverFinished]) {
        // Copy from previous founded printer list
        if (self->_tableData.count > 0) {
            printerList = self->_tableData.mutableCopy;
        }
        NSArray *lanPrinterlist = [PrinterManager getLanPrinterList];
        if (lanPrinterlist != nil && lanPrinterlist.count > 0) {
            if (printerList != nil && printerList.count > 0) {
                for (int i = 0; i < lanPrinterlist.count; i++) {
                    BOOL isPrinterExist = NO;
                    SIIMpaDiscoveredPrinter *printer = [lanPrinterlist objectAtIndex:i];
                    for (int j = 0; j < printerList.count ; j++) {
                        SIIMpaDiscoveredPrinter *existPrinter = [printerList objectAtIndex:j];
                        if ([printer.ipAddress isEqualToString:existPrinter.ipAddress]) {
                            isPrinterExist = YES;
                            break;
                        }
                    }
                    if (!isPrinterExist) {
                        [printerList addObject:[lanPrinterlist objectAtIndex:i]];
                    }
                }
            } else {
                [printerList addObjectsFromArray:lanPrinterlist];
            }
            self->_tableData = printerList;
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.tableView reloadData];
            });
        }
        [NSThread sleepForTimeInterval:0.01];
    }
}

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

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

@end
