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

#import "AddressListViewController.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 <BlocksKit/BlocksKit.h>
#import <libextobjc/EXTScope.h>
#import "Utility.h"
#import "WebService.h"
#import "AddressDetailViewController.h"
#import "Vars.h"

NSString *const AddressDidSelectNotification = @"AddressDidSelectNotification";

@interface AddressListViewController () <DZNEmptyDataSetDefault>

@property (nonatomic, strong) Address *selectedAddress;

@property (nonatomic, copy) void (^didSelectBlock) (Address *address);
@property (nonatomic, copy) void (^didInsertBlock) (Address *address);
@property (nonatomic, copy) void (^didUpdateBlock) (Address *address);
@property (nonatomic, copy) void (^didDeleteBlock) (Address *address);

@property (nonatomic, strong) NSMutableArray *cellDataArray;

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

@end

@implementation AddressListViewController

- (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(didInsertAddress:) name:AddressDidInsertNotification object:nil];
	[notificationCenter addObserver:self selector:@selector(didUpdateAddress:) name:AddressDidUpdateNotification object:nil];
	[notificationCenter addObserver:self selector:@selector(didDeleteAddress:) name:AddressDidDeleteNotification object:nil];

	if ([StringUtils isEmpty:self.title]) {
		NSString *addressTypeString = IMLocalizedString(@"Address");
		if (self.addressType == AddressTypeContactInfo) {
			addressTypeString = IMLocalizedString(@"Contact Information");
		}
		self.title = [NSString stringWithFormat:IMLocalizedString(@"Manage %@"), addressTypeString];
	}

	[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)selectAddress:(Address *)address {
	self.selectedAddress = address;
}

#pragma mark - Network

- (void)removeAddress:(Address *)address {
	if (address.transient) {
		[self sendActionToDeleteAddress:address withDefaultId:-1];
		return;
	}

	RemoveAddress *removeAddress = [[RemoveAddress alloc] init];
	removeAddress.aid = address.aid;

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

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

#pragma mark - Action

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

#pragma mark - Segue

- (void)performSegueForAddress:(Address *)address {
	AddressDetailViewController *viewController = [[AddressDetailViewController alloc] initWithAddress:address];
	viewController.addressType = self.addressType;
	viewController.allowsTransient = self.allowsTransient;
	viewController.allowsDefault = self.allowsDefault;
	[viewController setDidInsertBlock:^(Address *address) {
		[self.navigationController popViewControllerAnimated:YES];
	}];
	[viewController setDidUpdateBlock:^(Address *address) {
		[self.navigationController popViewControllerAnimated:YES];
	}];
	[viewController setDidDeleteBlock:^(Address *address) {
		[self.navigationController popViewControllerAnimated:YES];
	}];
	[self.navigationController pushViewController:viewController animated:YES];
}

#pragma mark - Notification

- (void)didInsertAddress:(NSNotification *)notification {
	Address *address = notification.object;
	if (address.isDefault) {
		[self.addresses enumerateObjectsUsingBlock:^(Address *obj, NSUInteger idx, BOOL *stop) {
			if ([obj isEqual:address]) {
				return;
			}
			if (obj.isDefault) {
				obj.isDefault = NO;
				[self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:idx inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
			}
		}];
	}
	if (![self.addresses containsObject:address]) {
		NSInteger idx = self.addresses.count;
		[self.addresses addObject:address];
		[self.cellDataArray addObject:[self convertTableViewCellDataFromAddress:address]];
		[self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:idx inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
		[self.tableView reloadEmptyDataSet];
	}
	if (self.allowsSelection && self.addresses.count == 1) {
		self.selectedAddress = [Address primaryOfAddresses:self.addresses];
		NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
		[notificationCenter postNotificationName:AddressDidSelectNotification object:address];
	}
	if (self.didInsertBlock) {
		self.didInsertBlock(address);
	}
}

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

- (void)didDeleteAddress:(NSNotification *)notification {
	Address *address = notification.object;
	if ([self.addresses containsObject:address]) {
		NSInteger idx = [self.addresses indexOfObject:address];
		[self.addresses removeObjectAtIndex:idx];
		[self.cellDataArray removeObjectAtIndex:idx];
		[self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:idx inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
		[self.tableView reloadEmptyDataSet];
	}
	if (self.allowsSelection && [self.selectedAddress isEqual:address]) {
		self.selectedAddress = [Address primaryOfAddresses:self.addresses];
		NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
		[notificationCenter postNotificationName:AddressDidSelectNotification object:address];
	}
	if (self.didDeleteBlock) {
		self.didDeleteBlock(address);
	}
}

#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) {
			[self performSegueForAddress:nil];
		}];
	} else {
		self.navigationItem.leftBarButtonItem = nil;
		self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] im_initWithBarButtonSystemItem:UIBarButtonSystemItemAdd handler:^(UIBarButtonItem *barButtonItem) {
			@strongify(self)
			[self performSegueForAddress: nil];
		}];
	}
}

- (TableViewCellData *)convertTableViewCellDataFromAddress:(Address *)address {
	@weakify(self)
	TableViewCellData *data = [[TableViewCellData alloc] init];
	data.style = UITableViewCellStyleSubtitle;
	[data setTextBlock:^NSString *{
		return address.fullName;
	}];
	[data setDetailAttributedTextBlock:^NSAttributedString *{
		return address.attributedEmailIfDefaultAppending;
	}];
	[data setAccessoryTypeBlock:^UITableViewCellAccessoryType {
		@strongify(self)
		if (self.isSelection) {
			if ([address isEqual:self.selectedAddress]) {
				return UITableViewCellAccessoryCheckmark;
			} else {
				return UITableViewCellAccessoryNone;
			}
		} else {
			return UITableViewCellAccessoryDisclosureIndicator;
		}
	}];
	[data setDidSelectBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data) {
		@strongify(self)
		if (self.isSelection) {
			self.selectedAddress = address;
			NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
			[notificationCenter postNotificationName:AddressDidSelectNotification object:address];
			if (self.didSelectBlock) {
				self.didSelectBlock(address);
			}
		} else {
			[self performSegueForAddress:address];
		}
	}];
	return data;
}

- (void)buildCellDataSource {
	NSMutableArray *array = self.cellDataArray;
	for (Address *address in self.addresses) {
		[array addObject:[self convertTableViewCellDataFromAddress:address]];
	}
}

- (void)sendActionToDeleteAddress:(Address *)address withDefaultId:(NSInteger)defaultId {
	NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
	[notificationCenter postNotificationName:AddressDidDeleteNotification object:address userInfo:defaultId >= 0 ? @{ AddressDefaultIdUserInfoKey : @(defaultId) } : nil];
	if (self.didDeleteBlock) {
		self.didDeleteBlock(address);
	}
}

#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 removeAddress:self.addresses[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:AddressDidInsertNotification object:nil];
	[notificationCenter removeObserver:self name:AddressDidUpdateNotification object:nil];
	[notificationCenter removeObserver:self name:AddressDidDeleteNotification object:nil];
}

@end
