//
// CreditCardListViewController.m
// Project
//
// Created by Ziv on 16/5/30.
//
//

#import "CreditCardListViewController.h"
#import "Lang.h"
#import "SDK.h"
#import "BeanUtils.h"
#import "CocoaUtils.h"
#import "DrawUtils.h"
#import "UIConstants.h"
#import "UIToolkit.h"
#import "DZNEmptyDataSetDefault.h"
#import <libextobjc/EXTScope.h>
#import "Utility.h"
#import "WebService.h"
#import "CreditCardDetailViewController.h"
#import "Vars.h"

NSString *const CreditCardDidSelectNotification = @"CreditCardDidSelectNotification";

@interface CreditCardListViewController () <DZNEmptyDataSetDefault>

@property (nonatomic, strong) CreditCard *selectedCreditCard;

@property (nonatomic, copy) void (^didSelectBlock) (CreditCard *creditCard);
@property (nonatomic, copy) void (^didInsertBlock) (CreditCard *creditCard);
@property (nonatomic, copy) void (^didUpdateBlock) (CreditCard *creditCard);
@property (nonatomic, copy) void (^didDeleteBlock) (CreditCard *creditCard);

@property (nonatomic, strong) NSMutableArray *cellDataArray;

@property (nonatomic, assign, readonly) BOOL allowsSimulate;

@end

@implementation CreditCardListViewController

- (instancetype)init {
	if (self = [super init]) {
		// avoid notification conflict with checkout
		self.hidesBottomBarWhenPushed = YES;
		self.title = @"";
		[[Vars appDelegate] applyDefaultConfigurationForViewController:self];
	}
	return self;
}

- (void)viewDidLoad {
	[super viewDidLoad];

	self.cellDataArray = [NSMutableArray array];

	NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
	[notificationCenter addObserver:self selector:@selector(didInsertCreditCard:) name:CreditCardDidInsertNotification object:nil];
	[notificationCenter addObserver:self selector:@selector(didUpdateCreditCard:) name:CreditCardDidUpdateNotification object:nil];
	[notificationCenter addObserver:self selector:@selector(didDeleteCreditCard:) name:CreditCardDidDeleteNotification object:nil];

	if ([StringUtils isEmpty:self.title]) {
		self.title = [NSString stringWithFormat:IMLocalizedString(@"Manage %@"), IMLocalizedString(@"Credit Card")];
	}

	[self updateManageButtonItem];

	self.tableView.emptyDataSetSource = self;
	[self buildCellDataSource];
}

#pragma mark - Property

- (BOOL)allowsSimulate {
#if DEBUG
	return [Vars is_develop];
#else
	return NO;
#endif
}

#pragma mark - Public

- (void)selectCreditCard:(CreditCard *)creditCard {
	self.selectedCreditCard = creditCard;
}

#pragma mark - Network

- (void)removeCreditCard:(CreditCard *)creditCard {
	if (creditCard.transient) {
		[self sendActionToDeleteCreditCard:creditCard withDefaultId:-1];
		return;
	}

	RemoveCreditCard *removeCreditCard = [[RemoveCreditCard alloc] init];
	removeCreditCard.ccid = creditCard.ccid;

	NSDictionary *requestDict = [Utility perlParamXml:[removeCreditCard innerXML] action:removeCreditCard.name];

	[Utility getXMLFromRequestWithMethod:@"GET" url:removeCreditCard.address parameters:requestDict success:^(NSString *xml) {
		NSString *responseStr = xml;
		// NSLog(@"%@", responseStr);
		WebServiceResponseJsonMapper *mapper = [[WebServiceResponseJsonMapper alloc] initWithClass:[RemoveCreditCardResponse class]];
		NSDictionary *jsonDict = [Utility JSONObjectWithXMLString:responseStr objectMapping:mapper.objectMapping];
		if (![mapper parseWithJSONObject:jsonDict]) {
			RemoveCreditCardResponse *response = mapper.response;
			if (response.error_code > 0) {
				[CocoaUtils showAlertWithTitle:IMLocalizedString(@"Error") message:response.error_message];
			} else {
				[self sendActionToDeleteCreditCard:creditCard withDefaultId:response.default_ccid];
			}
		}
	}];
}

#pragma mark - Action

- (void)manageAction {
	self.isSelection = !self.isSelection;
	[self updateManageButtonItem];
	[self.tableView reloadData];
}

#pragma mark - Segue

- (void)performSegueForCreditCard:(CreditCard *)creditCard {
	CreditCardDetailViewController *viewController = [[CreditCardDetailViewController alloc] initWithCreditCard:creditCard];
	viewController.allowsTransient = self.allowsTransient;
	viewController.allowsDefault = self.allowsDefault;
	[viewController setDidInsertBlock:^(CreditCard *creditCard) {
		[self.navigationController popViewControllerAnimated:YES];
	}];
	[viewController setDidUpdateBlock:^(CreditCard *creditCard) {
		[self.navigationController popViewControllerAnimated:YES];
	}];
	[viewController setDidDeleteBlock:^(CreditCard *creditCard) {
		[self.navigationController popViewControllerAnimated:YES];
	}];
	[self.navigationController pushViewController:viewController animated:YES];
}

#pragma mark - Notification

- (void)didInsertCreditCard:(NSNotification *)notification {
	CreditCard *creditCard = notification.object;
	if (creditCard.isDefault) {
		[self.creditCards enumerateObjectsUsingBlock:^(CreditCard *obj, NSUInteger idx, BOOL *stop) {
			if ([obj isEqual:creditCard]) {
				return;
			}
			if (obj.isDefault) {
				obj.isDefault = NO;
				[self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:idx inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
			}
		}];
	}
	if (![self.creditCards containsObject:creditCard]) {
		NSInteger idx = self.creditCards.count;
		[self.creditCards addObject:creditCard];
		[self.cellDataArray addObject:[self convertTableViewCellDataFromCreditCard:creditCard]];
		[self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:idx inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
		[self.tableView reloadEmptyDataSet];
	}
	if (self.allowsSelection && self.creditCards.count == 1) {
		self.selectedCreditCard = [CreditCard primaryOfCreditCards:self.creditCards];
		NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
		[notificationCenter postNotificationName:CreditCardDidSelectNotification object:creditCard];
	}
	if (self.didInsertBlock) {
		self.didInsertBlock(creditCard);
	}
}

- (void)didUpdateCreditCard:(NSNotification *)notification {
	Address *creditCard = notification.object;
	if (creditCard.isDefault) {
		[self.creditCards enumerateObjectsUsingBlock:^(Address *obj, NSUInteger idx, BOOL *stop) {
			if ([obj isEqual:creditCard]) {
				return;
			}
			if (obj.isDefault) {
				obj.isDefault = NO;
				[self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:idx inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
			}
		}];
	}
	if ([self.creditCards containsObject:creditCard]) {
		NSInteger idx = [self.creditCards indexOfObject:creditCard];
		[BeanUtils copyProperties:self.creditCards[idx] origin:creditCard];
		[self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:idx inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
	}
	if (self.allowsSelection && [self.selectedCreditCard isEqual:creditCard]) {
		NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
		[notificationCenter postNotificationName:CreditCardDidSelectNotification object:creditCard];
	}
	if (self.didUpdateBlock) {
		self.didUpdateBlock(creditCard);
	}
}

- (void)didDeleteCreditCard:(NSNotification *)notification {
	CreditCard *creditCard = notification.object;
	if ([self.creditCards containsObject:creditCard]) {
		NSInteger idx = [self.creditCards indexOfObject:creditCard];
		[self.creditCards removeObjectAtIndex:idx];
		[self.cellDataArray removeObjectAtIndex:idx];
		[self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:idx inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
		[self.tableView reloadEmptyDataSet];
	}
	if (self.allowsSelection && [self.selectedCreditCard isEqual:creditCard]) {
		self.selectedCreditCard = [CreditCard primaryOfCreditCards:self.creditCards];
		NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
		[notificationCenter postNotificationName:CreditCardDidSelectNotification object:creditCard];
	}
	if (self.didDeleteBlock) {
		self.didDeleteBlock(creditCard);
	}
}

#pragma mark - Private

- (void)updateManageButtonItem {
	@weakify(self)
	if (self.isSelection) {
		self.navigationItem.leftBarButtonItem = nil;
		self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(manageAction)];
	} else if (self.allowsSelection) {
		self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(manageAction)];
		self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] im_initWithBarButtonSystemItem:UIBarButtonSystemItemAdd handler:^(UIBarButtonItem *barButtonItem) {
			@strongify(self)
			[self performSegueForCreditCard: nil];
		}];
	} else {
		self.navigationItem.leftBarButtonItem = nil;
		self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] im_initWithBarButtonSystemItem:UIBarButtonSystemItemAdd handler:^(UIBarButtonItem *barButtonItem) {
			@strongify(self)
			[self performSegueForCreditCard: nil];
		}];
	}
}

- (TableViewCellData *)convertTableViewCellDataFromCreditCard:(CreditCard *)creditCard {
	@weakify(self)
	TableViewCellData *data = [[TableViewCellData alloc] init];
	data.style = UITableViewCellStyleSubtitle;
	[data setImageBlock:^UIImage *{
		return creditCard.cardTypeImage;
	}];
	[data setTextBlock:^NSString *{
		return creditCard.cardTypeName;
	}];
	[data setDetailAttributedTextBlock:^NSAttributedString *{
		return [creditCard attributedRedactedCardNumberIfDefaultAppendingWithFormat:@"**** %@"];
	}];
	[data setAccessoryTypeBlock:^UITableViewCellAccessoryType {
		@strongify(self)
		if (self.isSelection) {
			if ([creditCard isEqual:self.selectedCreditCard]) {
				return UITableViewCellAccessoryCheckmark;
			} else {
				return UITableViewCellAccessoryNone;
			}
		} else {
			return UITableViewCellAccessoryDisclosureIndicator;
		}
	}];
	[data setDidSelectBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data) {
		@strongify(self)
		if (self.isSelection) {
			self.selectedCreditCard = creditCard;
			NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
			[notificationCenter postNotificationName:CreditCardDidSelectNotification object:creditCard];
			if (self.didSelectBlock) {
				self.didSelectBlock(creditCard);
			}
		} else {
			[self performSegueForCreditCard:creditCard];
		}
	}];
	return data;
}

- (void)buildCellDataSource {
	NSMutableArray *array = self.cellDataArray;
	for (CreditCard *creditCard in self.creditCards) {
		[array addObject:[self convertTableViewCellDataFromCreditCard:creditCard]];
	}
}

- (void)sendActionToDeleteCreditCard:(CreditCard *)creditCard withDefaultId:(NSInteger)defaultId {
	NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
	[notificationCenter postNotificationName:CreditCardDidDeleteNotification object:creditCard userInfo:defaultId >= 0 ? @{ CreditCardDefaultIdUserInfoKey : @(defaultId) } : nil];
	if (self.didDeleteBlock) {
		self.didDeleteBlock(creditCard);
	}
}

#pragma mark - Table view data source

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

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
	TableViewCellData *data = self.cellDataArray[indexPath.row];
	return [UIToolkit tableView:tableView atIndexPath:indexPath cellWithData:data];
}

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
	return !self.isSelection;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
	if (editingStyle == UITableViewCellEditingStyleDelete) {
		[self removeCreditCard:self.creditCards[indexPath.row]];
	}
}

#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
	[tableView deselectRowAtIndexPath:indexPath animated:YES];
	TableViewCellData *data = self.cellDataArray[indexPath.row];
	[UIToolkit tableView:tableView atIndexPath:indexPath didSelectWithData:data];
}

#pragma mark

- (void)dealloc {
	NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
	[notificationCenter removeObserver:self name:CreditCardDidInsertNotification object:nil];
	[notificationCenter removeObserver:self name:CreditCardDidUpdateNotification object:nil];
	[notificationCenter removeObserver:self name:CreditCardDidDeleteNotification object:nil];
}

@end
