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

#import "AddressDetailViewController.h"
#import "Lang.h"
#import "SDK.h"
#import "CocoaUtils.h"
#import "UIConstants.h"
#import "UIToolkit.h"
#import <libextobjc/EXTScope.h>
#import <LoremIpsum/LoremIpsum.h>
#import "Utility.h"
#import "AddressListViewController.h"
#import "Vars.h"

NSString *const AddressDidInsertNotification = @"AddressDidInsertNotification";
NSString *const AddressDidUpdateNotification = @"AddressDidUpdateNotification";
NSString *const AddressDidDeleteNotification = @"AddressDidDeleteNotification";
NSString *const AddressDefaultIdUserInfoKey = @"AddressDefaultIdUserInfoKey";

@interface AddressDetailViewController ()

@property (nonatomic, copy) 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) NSArray *cellDataArrays;

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

@end

@implementation AddressDetailViewController

- (instancetype)initWithAddress:(Address *)address {
	if (self = [self init]) {
		self.address = address;
	}
	return self;
}

- (instancetype)init {
	if (self = [super init]) {
		self.title = @"";
		[[Vars appDelegate] applyDefaultConfigurationForViewController:self];
	}
	return self;
}

- (void)viewDidLoad {
	[super viewDidLoad];

	BOOL isExisted = self.address.aid > 0;

	NSString *addressTypeString = IMLocalizedString(@"Address");
	if (self.addressType == AddressTypeContactInfo) {
		addressTypeString = IMLocalizedString(@"Contact Information");
	}
	if (isExisted) {
		self.title = [NSString stringWithFormat:IMLocalizedString(@"Edit %@"), addressTypeString];
	} else {
		self.title = [NSString stringWithFormat:IMLocalizedString(@"Add %@"), addressTypeString];
	}
	if (isExisted) {
		self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash target:self action:@selector(removeAddress)];
	}

	if (YES) {
		UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth([UIScreen mainScreen].bounds), [UIConstants defaultTableViewRowHeight] + 15 * 2)];
		UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
		button.frame = CGRectMake(15, 15, CGRectGetWidth([UIScreen mainScreen].bounds) - 15 * 2, [UIConstants defaultTableViewRowHeight]);
		button.backgroundColor = [Vars defaultTintColor];
		button.titleLabel.font = [UIFont boldSystemFontOfSize:[UIFont buttonFontSize]];
		[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
		[button setTitle:IMLocalizedString(@"Save") forState:UIControlStateNormal];
		[button addTarget:self action:@selector(footerButtonAction) forControlEvents:UIControlEventTouchUpInside];
		[Utility addRoundedBorderToButton:button];
		[footerView addSubview:button];
		self.tableView.tableFooterView = footerView;
	}
	self.tableView.sectionHeaderHeight = [UIConstants defaultTableViewCellLayoutInsets].top;
	self.tableView.sectionFooterHeight = [UIConstants defaultTableViewCellLayoutInsets].bottom;
	[self buildCellDataSource];
}

#pragma mark - Property

- (Address *)address {
	if (!_address) {
		_address = self.allowsSimulate ? [Address randomAddressWithType:self.addressType] : [[Address alloc] initWithType:self.addressType];
		_address.transient = self.allowsTransient;
	}
	return _address;
}

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

#pragma mark - Network

- (void)updateAddress {
	BOOL isExisted = self.address.aid > 0;

	if (self.address.transient) {
		if (!isExisted) {
			self.address.aid = abs((int32_t)[LoremIpsum word].hash);
		}
		[self sendActionToUpdateAddress:self.address withDefaultId:-1 isExisted:isExisted];
		return;
	}

	UpdateAddress *updateAddress = [[UpdateAddress alloc] init];
	updateAddress.addressDetails = self.address;

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

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

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

	RemoveAddress *removeAddress = [[RemoveAddress alloc] init];
	removeAddress.aid = self.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:self.address withDefaultId:response.default_aid];
			}
		}
	}];
}

#pragma mark - Action

- (void)footerButtonAction {
	if ([self validateAddress]) {
		[self updateAddress];
	}
}

#pragma mark - Private

- (void)buildCellDataSource {
	NSMutableArray *arrays = [NSMutableArray array];
	if (self.addressType == AddressTypeContactInfo) {
		[arrays addObject:[Utility collectTableViewCellDataArrayWithContactInfo:self.address]];
	}
	if (self.allowsDefault) {
		TableViewCellData *data = [[TableViewCellData alloc] init];
		data.style = UITableViewCellStyleValue1;
		data.editingType = TableViewCellEditingTypeSwitch;
		data.text = IMLocalizedString(@"Default");
		data.keyPath = @"isDefault";
		data.observedObject = self.address;
		[arrays addObject:@[data]];
	}
	if (NO) {
		TableViewCellData *data = [[TableViewCellData alloc] init];
		data.text = IMLocalizedString(@"Any information you provide will only be used for processing your order and will not be sold, rented, leased or forwarded to any third party.");
		data.allowsTextLineWrapping = YES;
		[arrays addObject:@[data]];
	}
	self.cellDataArrays = [NSArray arrayWithArray:arrays];
}

- (BOOL)validateAddress {
	[self.tableView endEditing:YES];
	for (int section = 0; section < self.cellDataArrays.count; section++) {
		for (int row = 0; row < [self.cellDataArrays[section] count]; row++) {
			NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
			TableViewCellData *data = self.cellDataArrays[section][row];
			if (![data validateRequired]) {
				[CocoaUtils showAlertWithTitle:IMLocalizedString(@"Information") message:[data requiredValidationMessage:NO] dismissalHandler:^{
					[UIToolkit tableView:self.tableView atIndexPath:indexPath didFocusWithData:data];
				}];
				return NO;
			}
			if (![data validateIntegrity]) {
				[CocoaUtils showAlertWithTitle:IMLocalizedString(@"Information") message:[data integrityValidationMessage:NO] dismissalHandler:^{
					[UIToolkit tableView:self.tableView atIndexPath:indexPath didFocusWithData:data];
				}];
				return NO;
			}
		}
	}
	return YES;
}

- (void)sendActionToUpdateAddress:(Address *)address withDefaultId:(NSInteger)defaultId isExisted:(BOOL)isExisted {
	NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
	[notificationCenter postNotificationName:isExisted ? AddressDidUpdateNotification : AddressDidInsertNotification object:address userInfo:defaultId >= 0 ? @{ AddressDefaultIdUserInfoKey : @(defaultId) } : nil];
	if (isExisted) {
		if (self.didUpdateBlock) {
			self.didUpdateBlock(address);
		}
	} else {
		if (self.didInsertBlock) {
			self.didInsertBlock(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 self.cellDataArrays.count;
}

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

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

#pragma mark - Table view delegate

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
	TableViewCellData *data = self.cellDataArrays[indexPath.section][indexPath.row];
	return [UIToolkit tableView:tableView atIndexPath:indexPath rowHeightWithData:data];
}

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

@end
