//
//  ViewController.m
//  ASR033W
//
//  Created by MRX_ZYL on 13/10/2020.
//

#import "ViewController.h"
#import <ASR033WSDK/ASR033WSDK.h>
#import <SVProgressHUD/SVProgressHUD.h>
#import "EPCDataCell.h"
#import "EPCData.h"
#import "System.h"
#import "Utils.h"
#import "SearchViewController.h"

@interface ViewController ()<ASR033WDelegate,UITableViewDataSource,UITableViewDelegate,SearchInformationDelegate>
@property (weak, nonatomic) IBOutlet UITextField *ipTextField;
@property (weak, nonatomic) IBOutlet UITextField *portTextField;
@property (weak, nonatomic) IBOutlet UIButton *connectButton;
@property (weak, nonatomic) IBOutlet UIButton *disConnectButton;
@property (weak, nonatomic) IBOutlet UILabel *countLabel;
@property (weak, nonatomic) IBOutlet UILabel *totalLabel;
@property (weak, nonatomic) IBOutlet UIButton *startButton;
@property (weak, nonatomic) IBOutlet UIButton *stopButton;
@property (weak, nonatomic) IBOutlet UIButton *clearButton;
@property (weak, nonatomic) IBOutlet UIView *backGroundView;
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (weak, nonatomic) IBOutlet UIBarButtonItem *settingBarItem;
@property (weak, nonatomic) IBOutlet UILabel *temperatureLabel;
@property (weak, nonatomic) IBOutlet UISwitch *subscribeSwitch;
@property (weak, nonatomic) IBOutlet UISegmentedControl *modeSegment;
@property (weak, nonatomic) IBOutlet UIBarButtonItem *searchButton;
@end
@implementation ViewController{
    ASR033W *asr033w;
    System *system;
    NSMutableArray *dataArray;
    NSMutableDictionary *dataDic;
    NSMutableArray *arrIPs;
    int count;
    int total;
    EPCData *_epcData;
    NSTimer *getTemperatureTimer;
    BOOL inventoryStatus;
    ASR033WConnectMethod connectMethod;
    BOOL connectedStatus;
}
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:YES];
    asr033w.delegate = self;
    if (!asr033w.isConnected) {
        [self setDisconnectUI];
    }
}
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:YES];
    asr033w.delegate = nil;
    if (asr033w && asr033w.isConnected) {
        [asr033w stopInventory];
        self.stopButton.backgroundColor = [UIColor lightGrayColor];
        self.stopButton.userInteractionEnabled = NO;
        self.startButton.backgroundColor = [UIColor redColor];
        self.startButton.userInteractionEnabled = YES;
    }
}
- (void)viewDidLoad {
    [super viewDidLoad];
    connectedStatus = NO;
    system = [System sharedSystem];
    asr033w = [ASR033W sharedInstance];
    count = 0;
    total = 0;
    inventoryStatus = NO;
    dataArray = [[NSMutableArray alloc] init];
    dataDic = [[NSMutableDictionary alloc] init];
    arrIPs  = [[NSMutableArray alloc]init];
    [self setUI];
}
- (void)setUI {
    if (@available(iOS 15.0, *)){
        UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];
        appearance.backgroundEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleRegular];
        appearance.backgroundColor = [UIColor whiteColor];
        appearance.shadowColor = [UIColor lightGrayColor];
        self.navigationController.navigationBar.scrollEdgeAppearance = appearance;
        self.navigationController.navigationBar.standardAppearance = appearance;
    }
    [SVProgressHUD setDefaultMaskType:SVProgressHUDMaskTypeBlack];
    self.tableView.rowHeight = 90.f;
    self.backGroundView.layer.masksToBounds = YES;
    self.backGroundView.layer.borderWidth = 5;
    self.backGroundView.layer.borderColor = [[UIColor blackColor] CGColor];
    self.backGroundView.layer.cornerRadius = 1;
    self.connectButton.layer.masksToBounds = YES;
    self.connectButton.layer.cornerRadius = 5;
    self.disConnectButton.layer.masksToBounds = YES;
    self.disConnectButton.layer.cornerRadius = 5;
    self.startButton.layer.masksToBounds = YES;
    self.startButton.layer.cornerRadius = 5;
    self.stopButton.layer.masksToBounds = YES;
    self.stopButton.layer.cornerRadius = 5;
    self.clearButton.layer.masksToBounds = YES;
    self.clearButton.layer.cornerRadius = 5;
    self.settingBarItem.enabled = NO;
    self.ipTextField.userInteractionEnabled = YES;
    self.portTextField.userInteractionEnabled = YES;
    self.connectButton.userInteractionEnabled = YES;
    self.disConnectButton.userInteractionEnabled = NO;
    self.disConnectButton.backgroundColor = [UIColor lightGrayColor];
    self.startButton.userInteractionEnabled = NO;
    self.startButton.backgroundColor = [UIColor lightGrayColor];
    self.stopButton.userInteractionEnabled = NO;
    self.stopButton.backgroundColor = [UIColor lightGrayColor];
    self.clearButton.userInteractionEnabled = NO;
    self.clearButton.backgroundColor = [UIColor lightGrayColor];
    self.tableView.userInteractionEnabled = NO;
    if ([system getConnectMethod] == ConnectMethod_TCP) {
        connectMethod = ASR033WConnectMethod_TCP;
        self.ipTextField.text = [system getIp];
        self.portTextField.text = [system getPort];
        self.modeSegment.selectedSegmentIndex = 0;
    } else {
        connectMethod = ASR033WConnectMethod_MQTT;
        self.ipTextField.text = [system getMQTTIp];
        self.portTextField.text = [system getMQTTPort];
        self.modeSegment.selectedSegmentIndex = 1;
    }
}
#pragma mark - Action
- (IBAction)onClickConnectButton:(id)sender {
    NSLog(@"Connect");
    [self.view endEditing:YES];
    if ([self.ipTextField.text isEqualToString:@""]) {
        UIAlertController * alertController = [UIAlertController alertControllerWithTitle:@"" message:@"IP Input Error." preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction * cancelAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
           
        }];
        [alertController addAction:cancelAction];
        [self presentViewController:alertController animated:YES completion:nil];
        return;
    } else if ([self.portTextField.text isEqualToString:@""]
              || ![self isAllNum:self.portTextField.text]
              ||[self.portTextField.text intValue] > 65535) {
        UIAlertController * alertController = [UIAlertController alertControllerWithTitle:@"" message:@"Port Input Error." preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction * cancelAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
            
        }];
        [alertController addAction:cancelAction];
        [self presentViewController:alertController animated:YES completion:nil];
        return;
    }
    if (connectMethod == ASR033WConnectMethod_TCP) {
        [self->system setIp:self.ipTextField.text];
        [self->system setPort:self.portTextField.text];
    } else {
        [self->system setMQTTIp:self.ipTextField.text];
        [self->system setMQTTPort:self.portTextField.text];
    }
    asr033w.connectMethod = connectMethod;
    [self performSelector:@selector(dismissHUD) withObject:nil afterDelay:10];
    [SVProgressHUD showWithStatus:@"Connecting..."];
    [asr033w connectServerWithIP:self.ipTextField.text remoteport:[self.portTextField.text intValue]];
}
- (IBAction)onClickDisconnectButton:(id)sender {
    NSLog(@"Disconnect");
    [self.view endEditing:YES];
    [self performSelector:@selector(dismissHUD) withObject:nil afterDelay:10];
    [SVProgressHUD showWithStatus:@"Disconnecting..."];
    [asr033w disconnectServer];
}
- (IBAction)onClickSubscribeSwitch:(UISwitch *)sender {
    if (sender.isOn) {
        [asr033w startReceiveRFIDData];
    } else {
        [asr033w stopReceiveHIDData];
    }
    [system setSubscribeRFIDTopic:sender.isOn];
}
- (IBAction)onClickModeSegment:(UISegmentedControl *)sender {
    if (sender.selectedSegmentIndex == 0) {
        connectMethod = ASR033WConnectMethod_TCP;
        self.portTextField.text = [system getPort];
        [system setConnectMethod:ConnectMethod_TCP];
    } else {
        connectMethod = ASR033WConnectMethod_MQTT;
        self.portTextField.text = [system getMQTTPort];
        [system setConnectMethod:ConnectMethod_MQTT];
    }
}
- (IBAction)onClickStartInventoryButton:(id)sender {
    if (![Utils CheckSubscribeRFIDTopic]) {
        return;
    }
    [asr033w startInventoryWithAntenna1:YES antenna2:YES antenna3:YES antenna4:YES antenna5:YES antenna6:YES antenna7:YES antenna8:YES TID:YES];
}
- (IBAction)onClickStopInventoryButton:(id)sender {
    if (![Utils CheckSubscribeRFIDTopic]) {
        return;
    }
    [asr033w stopInventory];
}
- (IBAction)onClickClearButton:(id)sender {
    [dataArray removeAllObjects];
    [dataDic removeAllObjects];
    count = 0;
    total = 0;
    self.countLabel.text = @"0";
    self.totalLabel.text = @"0";
    [_tableView reloadData];
}
- (IBAction)onClickMore:(UIBarButtonItem *)sender {
    if (!inventoryStatus) {
        [self performSegueWithIdentifier:@"moreID" sender:nil];
    }
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    NSString *cellIdentifier = @"EPCDataCell";
    EPCDataCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if(!cell) {
        cell = [[[NSBundle mainBundle] loadNibNamed:@"EPCDataCell" owner:self options:nil] firstObject];
    }
    EPCData *epcData = [dataArray objectAtIndex:indexPath.row];
    if ([epcData.type isEqualToString:@"Barcode"]) {
        cell.epcLabel.text = [NSString stringWithFormat:@"HID Data: %@", epcData.epc];
        cell.phaseLabel.text = [NSString stringWithFormat:@"Count:%d", epcData.count];
    } else {
        cell.epcLabel.text = [NSString stringWithFormat:@"EPC:%@ TID:%@", epcData.epc ,epcData.tid];
        cell.phaseLabel.text = [NSString stringWithFormat:@"PC:%@  ANT:%@  Phase:%@", epcData.pc, epcData.antenna, epcData.phase];
        cell.countLabel.text = [NSString stringWithFormat:@"Frequency:%@  RSSI:%@  Count:%d", epcData.frequency,epcData.rssi,epcData.count];
    }
    
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    cell.accessoryType = UITableViewCellAccessoryNone;
    return cell;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
    if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
        [cell setLayoutMargins:UIEdgeInsetsZero];
    }
    if ([cell respondsToSelector:@selector(setSeparatorInset:)]){
        [cell setSeparatorInset:UIEdgeInsetsZero];
    }
}
#pragma mark - ASR033WDelegate
- (void)receivedASR033WSearchIP:(NSString *)IP isFinish:(BOOL)isFinish{
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        if(isFinish == YES)
        {
            self->connectedStatus = NO;
            if([SVProgressHUD isVisible]){
                [SVProgressHUD dismiss];
            }
            if ([self->arrIPs count]>0) {
                [self showAlertViewIPs];
            } else {
                UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"Search" message:@"Not found Devices" preferredStyle:UIAlertControllerStyleAlert];
                [alert addAction:[[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil] init]];
                [self presentViewController:alert animated:YES completion:nil];
            }
        } else {
            NSString *newString = [NSString stringWithFormat:@"%@", IP];
            if (![self->arrIPs containsObject:newString]) {
                [self->arrIPs addObject:newString];
            }
        }
    }];
}
- (void)receivedASR033WNetworkState:(ASR033WNetworkState)state error:(NSError *)error{
    NSLog(@"ASR033WetworkState = %lu error: %@",(unsigned long)state,error);
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(dismissHUD) object:nil];
        if (state == ASR033WNetworkStateConnected) {
            self.subscribeSwitch.userInteractionEnabled = YES;
            [self.subscribeSwitch setOn:[self->system getSubscribeRFIDTopic]];
            if ([self->system getSubscribeRFIDTopic]) {
                [self->asr033w startReceiveRFIDData];
            }
            [self->asr033w stopInventory];
            self.settingBarItem.enabled = YES;
            self.connectButton.userInteractionEnabled = NO;
            self.connectButton.backgroundColor = [UIColor lightGrayColor];
            self.disConnectButton.userInteractionEnabled = YES;
            self.disConnectButton.backgroundColor = [UIColor redColor];
            self.startButton.userInteractionEnabled = YES;
            self.startButton.backgroundColor = [UIColor redColor];
            self.stopButton.userInteractionEnabled = NO;
            self.stopButton.backgroundColor = [UIColor lightGrayColor];
            self.clearButton.userInteractionEnabled = YES;
            self.clearButton.backgroundColor = [UIColor redColor];
            self.tableView.userInteractionEnabled = YES;
            self.modeSegment.userInteractionEnabled = NO;
            self.temperatureLabel.text = @"";
            [self.tableView reloadData];
        } else {
            self.subscribeSwitch.userInteractionEnabled = NO;
            [self.subscribeSwitch setOn:NO];
            self.settingBarItem.enabled = NO;
            self.connectButton.userInteractionEnabled = YES;
            self.connectButton.backgroundColor = [UIColor redColor];
            self.disConnectButton.userInteractionEnabled = NO;
            self.disConnectButton.backgroundColor = [UIColor lightGrayColor];
            self.startButton.userInteractionEnabled = NO;
            self.startButton.backgroundColor = [UIColor lightGrayColor];
            self.stopButton.userInteractionEnabled = NO;
            self.stopButton.backgroundColor = [UIColor lightGrayColor];
            self.clearButton.userInteractionEnabled = NO;
            self.clearButton.backgroundColor = [UIColor lightGrayColor];
            self.tableView.userInteractionEnabled = NO;
            self.modeSegment.userInteractionEnabled = YES;
            self.temperatureLabel.text = @"";
        }
        if (error) {
            NSString *errReason = [NSString stringWithFormat:@"ErrCode %d : %@",(int)[error code],[error localizedDescription]];
            UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"Error" message:errReason preferredStyle:UIAlertControllerStyleAlert];
            [alert  addAction:[[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil] init]];
            [self presentViewController:alert animated:YES completion:nil];
        }
        if (self->connectedStatus) {
            self->connectedStatus = NO;
            return;
        }
        if ([SVProgressHUD isVisible]){
            [SVProgressHUD dismissWithDelay:0.2];
        }
    }];
}
- (void)receivedASR033WInventoryPC:(NSString *)pc epc:(NSString *)epc tid:(NSString *)tid ant:(int)ant rssi:(int)rssi phase:(float)phase frequency:(float)frequency{
    NSLog (@"APP pc = %@, epc = %@, tid = %@, ant = %d, RSSI = %d, phase = %f, frequency = %f", pc, epc, tid, ant, rssi, phase, frequency);
    total ++;
    dispatch_queue_t queue =  dispatch_queue_create("queue",DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{
        @synchronized (self) {
            @try {
                EPCData *epcData = [self->dataDic objectForKey:epc];
                if (epcData) {
                    epcData.count = epcData.count + 1;
                    epcData.rssi = [NSString stringWithFormat:@"%d", rssi];
                    epcData.phase = [NSString stringWithFormat:@"%.1f", phase];
                    epcData.frequency = [NSString stringWithFormat:@"%.3f", frequency];
                    epcData.tid = tid;
                    epcData.antenna = [NSString stringWithFormat:@"%d", ant];
                } else {
                    epcData = [[EPCData alloc] init];
                    epcData.rssi = [NSString stringWithFormat:@"%d", rssi];
                    epcData.phase = [NSString stringWithFormat:@"%.1f", phase];
                    epcData.frequency = [NSString stringWithFormat:@"%.3f", frequency];
                    epcData.epc = epc;
                    epcData.pc = pc;
                    epcData.tid = tid;
                    epcData.antenna = [NSString stringWithFormat:@"%d", ant];
                    epcData.count = 1;
                    epcData.type = @"RFID";
                    [self->dataArray addObject:epcData];
                    [self->dataDic setObject:epcData forKey:epc];
                    self->count ++;
                }
            } @catch (NSException *exception) {
                
            } @finally {
                
            }
            dispatch_async(dispatch_get_main_queue(), ^{
                self.countLabel.text = [NSString stringWithFormat:@"%d", self->count];
                self.totalLabel.text = [NSString stringWithFormat:@"%d", self->total];
                [self->_tableView reloadData];
            });
        }
    });
}
- (void)receivedASR033WHIDData:(NSData *)HIDData{
    dispatch_queue_t queue =  dispatch_queue_create("queue",DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{
        NSString *barcode = [[ NSString alloc] initWithData:HIDData encoding:NSASCIIStringEncoding];
        @synchronized (self) {
            self->total++;
            EPCData *epcData = [self->dataDic objectForKey:barcode];
            if (epcData) {
                epcData.count = epcData.count + 1;
            }else{
                epcData = [[EPCData alloc] init];
                epcData.type = @"Barcode";
                epcData.epc = barcode;
                epcData.count = 1;
                [self->dataDic setObject:epcData forKey:barcode];
                [self->dataArray addObject:epcData];
                self->count++;
            }
            dispatch_async(dispatch_get_main_queue(), ^{
                self.countLabel.text = [NSString stringWithFormat:@"%d",self->count];
                self.totalLabel.text = [NSString stringWithFormat:@"%d",self->total];
                [self.tableView reloadData];
            });
        }
    });
}

- (void)receivedASR033WActionState:(ASR033WCommandType)action resultCode:(ASR033WResultCode)resultCode {
    if (action == ASR033WCommandStop) {
        self.stopButton.backgroundColor = [UIColor lightGrayColor];
        self.stopButton.userInteractionEnabled = NO;
        self.startButton.backgroundColor = [UIColor redColor];
        self.startButton.userInteractionEnabled = YES;
        inventoryStatus = NO;
    } else if (action == ASR033WCommandInventory) {
        self.stopButton.backgroundColor = [UIColor redColor];
        self.stopButton.userInteractionEnabled = YES;
        self.startButton.backgroundColor = [UIColor lightGrayColor];
        self.startButton.userInteractionEnabled = NO;
        inventoryStatus = YES;
    }
}
- (void)receivedASR033WDeviceState:(ASR033WResultCode)error {
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        if (error != ASR033WResultNoError) {
            [Utils showAlert:@"Error" message:@"Failed to get response. Try again."];
        }
    }];
}
#pragma mark - Private
- (void)showAlertViewIPs
{
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Found Device"
                                                                   message:@"Please select device IP and Port"
                                                            preferredStyle:UIAlertControllerStyleActionSheet];
    for (NSString *ipString in arrIPs) {
        UIAlertAction *ip = [UIAlertAction actionWithTitle:ipString
                                                     style:UIAlertActionStyleDefault
                                                   handler:^(UIAlertAction * action) {
            self.ipTextField.text = ipString;
            self->asr033w.connectMethod = self->connectMethod;
            if (self->connectMethod == ASR033WConnectMethod_TCP) {
                [self->system setIp:ipString];
            } else {
                [self->system setMQTTIp:ipString];
            }
            int port = [self.portTextField.text intValue];
            [self performSelector:@selector(dismissHUD) withObject:nil afterDelay:10];
            [SVProgressHUD showWithStatus:@"Connecting..."];
            [self->asr033w connectServerWithIP:ipString remoteport:port];
        }];
        [alert addAction:ip];
    }
    
    UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel"
                                                     style:UIAlertActionStyleDefault
                                                   handler:nil];
    [alert addAction:cancel];
    
    alert.popoverPresentationController.barButtonItem = self.searchButton;
      alert.popoverPresentationController.sourceView = self.view;
    [self presentViewController:alert animated:YES completion:nil];
}
- (void)setDisconnectUI {
    self.settingBarItem.enabled = NO;
    self.connectButton.userInteractionEnabled = YES;
    self.connectButton.backgroundColor = [UIColor redColor];
    self.disConnectButton.userInteractionEnabled = NO;
    self.disConnectButton.backgroundColor = [UIColor lightGrayColor];
    self.startButton.userInteractionEnabled = NO;
    self.startButton.backgroundColor = [UIColor lightGrayColor];
    self.stopButton.userInteractionEnabled = NO;
    self.stopButton.backgroundColor = [UIColor lightGrayColor];
    self.clearButton.userInteractionEnabled = NO;
    self.clearButton.backgroundColor = [UIColor lightGrayColor];
    self.tableView.userInteractionEnabled = NO;
    self.subscribeSwitch.userInteractionEnabled = NO;
    self.modeSegment.userInteractionEnabled = YES;
}
- (BOOL)isIpAddress:(NSString *)iPAddress
{
    NSString *ipRegex = @"((25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))\\.){3}(25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))";
    NSPredicate *ipPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",ipRegex];
    return [ipPredicate evaluateWithObject:iPAddress];
}

- (BOOL)isAllNum:(NSString *)checkedNumString
{
    checkedNumString = [checkedNumString stringByTrimmingCharactersInSet:[NSCharacterSet decimalDigitCharacterSet]];
    if(checkedNumString.length > 0) {
        return NO;
    }
    return YES;
}
- (void)dismissHUD {
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        if ([SVProgressHUD isVisible]){
            [SVProgressHUD dismiss];
        }
    }];
}
#pragma mark - System
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self.view endEditing:YES];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"SearchListID"]) {
        SearchViewController *dataVC = segue.destinationViewController;
        dataVC.delegate = self;
    }
}
#pragma mark - SearchInformationDelegate
- (void)searchIP:(NSString *)ip port:(int)port {
    self->asr033w.connectMethod = self->connectMethod;
    if (self->connectMethod == ASR033WConnectMethod_TCP) {
        [self->system setIp:ip];
    } else {
        [self->system setMQTTIp:ip];
    }
    self.ipTextField.text = ip;
    int portValue = [self.portTextField.text intValue];
    [self performSelector:@selector(dismissHUD) withObject:nil afterDelay:10];
    [SVProgressHUD showWithStatus:@"Connecting..."];
    [self->asr033w connectServerWithIP:ip remoteport:portValue];
}
@end
