//
// RoomBasedSelectionViewController.m
// IvyMedia
//
// Created by haibara on 9/26/14.
//
//

#import "RoomBasedCountViewController.h"
#import "SDK.h"
#import "BeanUtils.h"
#import "CocoaUtils.h"
#import "UIConstants.h"
#import "UIToolkit.h"
#import <BlocksKit/BlocksKit+UIKit.h>
#import <libextobjc/EXTScope.h>
#import "Utility.h"
#import "Vars.h"

@interface RoomBasedCountData () <NSCopying>
@property (nonatomic, strong) NSMutableDictionary *memberNumbers;
@property (nonatomic, strong) NSMutableArray *childrenAge;
@end

@implementation RoomBasedCountData

- (instancetype)init {
	self = [super init];
	if (self) {
		self.memberNumbers = [NSMutableDictionary dictionary];
		self.childrenAge = [NSMutableArray array];
	}
	return self;
}

- (BOOL)isEqual:(id)object {
	if (self == object) {
		return YES;
	}
	if (![object isKindOfClass:self.class]) {
		return NO;
	}
    return [[BeanUtils describe:self] isEqualToDictionary:[BeanUtils describe:object]];
}

- (id)copyWithZone:(NSZone *)zone {
	RoomBasedCountData *countData = [BeanUtils copyWithZone:zone origin:self];
	countData.memberNumbers = [self.memberNumbers mutableCopyWithZone:zone];
	countData.childrenAge = [self.childrenAge mutableCopyWithZone:zone];
	return countData;
}

#pragma mark - Public

- (instancetype)initWithRoomNo:(NSInteger)roomNo {
	self = [self init];
	if (self) {
		self.roomNo = roomNo;
	}
	return self;
}

- (NSInteger)adultCount {
	return [self.memberNumbers[@"Adult"] intValue];
}

- (NSInteger)childCount {
	return [self.memberNumbers[@"Child"] intValue];
}

- (NSInteger)infantCount {
	return [self.memberNumbers[@"Infant"] intValue];
}

- (void)setAdultCount:(NSInteger)count {
	self.memberNumbers[@"Adult"] = @(count);
}

- (void)setChildCount:(NSInteger)count {
	self.memberNumbers[@"Child"] = @(count);
}

- (void)setInfantCount:(NSInteger)count {
	self.memberNumbers[@"Infant"] = @(count);
}

- (NSInteger)peopleCount {
	return self.adultCount + self.childCount + self.infantCount;
}

- (NSArray *)childAges {
	return [NSArray arrayWithArray:self.childrenAge];
}

- (void)configureWithRoomBasedPrice:(RoomBasedPrice *)price {
	self.adultCount = 2;
	self.childCount = MAX(MIN(price.min_people_num - self.adultCount, price.max_child_num), 0);
	self.infantCount = MAX(MIN(price.min_people_num - self.adultCount - self.childCount, price.max_infant_num), 0);
}

@end

@interface RoomBasedCountViewController ()

@property (nonatomic, strong) NSMutableArray *cellDataArrays;
@property (nonatomic, strong) NSMutableArray *countDatas;

@property (nonatomic, copy) void (^didDoneBlock) (NSArray *countDatas);
@property (nonatomic, copy) void (^didCancelBlock) (void);

@property (nonatomic, strong, readonly) NSArray *childrenAgeText;
@property (nonatomic, strong, readonly) NSArray *childrenAgeValue;
@property (nonatomic, assign, readwrite) NSInteger roomCount;

@end

@implementation RoomBasedCountViewController

- (instancetype)initWithRoomBasedCountDatas:(NSArray *)countDatas {
	self = [self init];
	if (self) {
		self.countDatas = [[NSMutableArray alloc] initWithArray:countDatas copyItems:YES];
	}
	return self;
}

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

- (void)viewDidLoad {
	[super viewDidLoad];

	@weakify(self)
	if (self.didCancelBlock) {
		self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] im_initWithBarButtonSystemItem:UIBarButtonSystemItemCancel handler:^(UIBarButtonItem *barButtonItem) {
			@strongify(self)
			self.didCancelBlock();
		}];
	}
	if (self.didDoneBlock) {
		self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] im_initWithBarButtonSystemItem:UIBarButtonSystemItemDone handler:^(UIBarButtonItem *barButtonItem) {
			@strongify(self)
			if (![self validateCount]) {
				return;
			}
			self.didDoneBlock([NSArray arrayWithArray:self.countDatas]);
		}];
	}

	self.tableView.sectionHeaderHeight = [UIConstants defaultTableViewCellLayoutInsets].top;
	self.tableView.sectionFooterHeight = [UIConstants defaultTableViewCellLayoutInsets].bottom;
	[self buildCellDataSource];
}

#pragma mark - Public

- (BOOL)childAgeEnabled {
	return self.minimumChildAge >= 0 && self.maximumChildAge > 0;
}

- (void)setPropertiesWithRoomBasedPrice:(RoomBasedPrice *)price {
	self.childEnabled = price.enable_child;
	self.infantEnabled = price.enable_infant;
	self.minimumPeopleCount = price.min_people_num;
	self.maximumPeopleCount = price.max_people_num;
	self.minimumAdultCount = price.min_adult_num;
	self.maximumAdultCount = price.max_adult_num;
	self.maximumChildCount = price.max_child_num;
	self.maximumInfantCount = price.max_infant_num;
	self.minimumChildAge = price.child_age_from;
	self.maximumChildAge = price.child_age_to;
	self.maxPeople = price.maxPeople;
	self.peoleMinimum = price.peopleMinimum;
}

#pragma mark - Property

- (NSArray *)childrenAgeValue {
	NSMutableArray *ageValue = [NSMutableArray array];
	for (NSInteger age = self.minimumChildAge; age <= self.maximumChildAge; ++age) {
		[ageValue addObject:@(age)];
	}
	return [NSArray arrayWithArray:ageValue];
}

- (NSArray *)childrenAgeText {
	NSMutableArray *ageText = [NSMutableArray array];
	for (NSInteger age = self.minimumChildAge; age <= self.maximumChildAge; ++age) {
		[ageText addObject:[NSString stringWithFormat:age > 1 ? IMLocalizedString(@"%d years old") : IMLocalizedString(@"%d year old"), age]];
	}
	return [NSArray arrayWithArray:ageText];
}

- (NSInteger)roomCount {
	return self.countDatas.count;
}

- (void)setRoomCount:(NSInteger)roomCount {
	NSInteger oldCount = self.countDatas.count;
	NSInteger newCount = roomCount;
	if (oldCount < newCount) {
		for (NSInteger roomNo = oldCount + 1; roomNo <= newCount; roomNo++) {
			RoomBasedCountData *countData = [[RoomBasedCountData alloc] initWithRoomNo:roomNo];
			[self configureRoomBasedCountData:countData];
			for (int i = 0; i < countData.childCount; i++) {
				[self insertChildAgeIntoRoomBasedCountData:countData];
			}
			[self.countDatas addObject:countData];
			[self.cellDataArrays addObject:[self collectTableViewCellDataArrayWithRoomBasedCountData:countData]];
		}
		[self.tableView insertSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1 + oldCount, newCount - oldCount)] withRowAnimation:UITableViewRowAnimationNone];
	} else if (oldCount > newCount) {
		[self.countDatas removeObjectsInRange:NSMakeRange(newCount, oldCount - newCount)];
		[self.cellDataArrays removeObjectsInRange:NSMakeRange(1 + newCount, oldCount - newCount)];
		[self.tableView deleteSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1 + newCount, oldCount - newCount)] withRowAnimation:UITableViewRowAnimationNone];
	}
}

#pragma mark - Action

- (void)changeChildCount:(NSInteger)childCount ofRoomBasedCountData:(RoomBasedCountData *)countData {
	NSMutableArray *array = self.cellDataArrays[countData.roomNo];
	NSInteger oldCount = countData.childrenAge.count;
	NSInteger newCount = childCount;
	NSMutableArray *indexPaths = [NSMutableArray array];
	if (oldCount < newCount) {
		for (NSInteger i = oldCount; i < newCount; i++) {
			[indexPaths addObject:[NSIndexPath indexPathForRow:i + 2 inSection:countData.roomNo]];
			[self insertChildAgeIntoRoomBasedCountData:countData];
			[array insertObject:[self createTableViewCellDataForChildAgeAtIndex:i ofRoomBasedCountData:countData] atIndex:2 + i];
		}
		[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
	} else if (oldCount > newCount) {
		for (NSInteger i = oldCount; i > newCount; i--) {
			[indexPaths addObject:[NSIndexPath indexPathForRow:i + 1 inSection:countData.roomNo]];
		}
		[countData.childrenAge removeObjectsInRange:NSMakeRange(newCount, oldCount - newCount)];
		[array removeObjectsInRange:NSMakeRange(2 + newCount, oldCount - newCount)];
		[self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
	}
}

#pragma mark - Private

- (TableViewCellData *)createTableViewCellDataForChildAgeAtIndex:(NSInteger)index ofRoomBasedCountData:(RoomBasedCountData *)countData {
	NSMutableString *string = [NSMutableString string];
	[string im_appendString:IMLocalizedString(@"Child")];
	[string im_appendString:WORD_DIVIDER_SPACE];
	[string appendFormat:@"%d", index + 1];
	TableViewCellData *data = [[TableViewCellData alloc] init];
	data.style = UITableViewCellStyleValue1;
	data.editingType = TableViewCellEditingTypePickerView;
	data.text = [NSString stringWithString:string];
	data.detailTextColor = [Vars defaultTintColor];
	data.optionTexts = self.childrenAgeText;
	data.optionValues = self.childrenAgeValue;
	data.observedObject = countData.childrenAge;
	data.keyPath = @(index);
	return data;
}

- (NSMutableArray *)collectTableViewCellDataArrayWithRoomBasedCountData:(RoomBasedCountData *)countData {
	NSMutableArray *array = [NSMutableArray array];
	@weakify(self)
	if (YES) {
		TableViewCellData *data = [[TableViewCellData alloc] init];
		data.style = UITableViewCellStyleValue1;
		data.text = IMLocalizedString(@"Adult");
		data.editingType = TableViewCellEditingTypeStepper;
		data.observedObject = countData;
		data.keyPath = @"adultCount";
		data.minimumValue = @(MAX(self.minimumAdultCount, 1));
		data.maximumValue = @(MAX(self.maximumAdultCount, 0));
		[array addObject:data];
	}
	if (self.childEnabled) {
		if (YES) {
			TableViewCellData *data = [[TableViewCellData alloc] init];
			data.style = UITableViewCellStyleValue1;
			data.text = IMLocalizedString(@"Child");
			data.editingType = TableViewCellEditingTypeStepper;
			data.observedObject = countData;
			data.keyPath = @"childCount";
			data.maximumValue = @(MAX(self.maximumChildCount, 0));
			if (self.childAgeEnabled) {
				@weakify(countData)
				[data setValueChangedPostActionBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data, IMStepper *stepper) {
					@strongify(self)
					// avoid countData cycle retain
					@strongify(countData)
					[self changeChildCount:(int)stepper.value ofRoomBasedCountData: countData];
				}];
			}
			[array addObject:data];
		}
		if (self.childAgeEnabled) {
			for (int i = 0; i < countData.childCount; ++i) {
				[array addObject:[self createTableViewCellDataForChildAgeAtIndex:i ofRoomBasedCountData:countData]];
			}
		}
	}
	if (self.infantEnabled) {
		TableViewCellData *data = [[TableViewCellData alloc] init];
		data.style = UITableViewCellStyleValue1;
		data.text = IMLocalizedString(@"Infant");
		data.editingType = TableViewCellEditingTypeStepper;
		data.observedObject = countData;
		data.keyPath = @"infantCount";
		data.maximumValue = @(MAX(self.maximumInfantCount, 0));
		[array addObject:data];
	}
	return array;
}

- (void)buildCellDataSource {
	NSMutableArray *arrays = [NSMutableArray array];
	if (YES) {
		TableViewCellData *data = [[TableViewCellData alloc] init];
		data.style = UITableViewCellStyleValue1;
		data.text = IMLocalizedString(@"Room");
		data.editingType = TableViewCellEditingTypeStepper;
		data.observedObject = self;
		data.keyPath = @"roomCount";
		data.minimumValue = @1;
		data.stepValue = @1;
		[arrays addObject:@[data]];
	}
	for (RoomBasedCountData *countData in self.countDatas) {
		[arrays addObject:[self collectTableViewCellDataArrayWithRoomBasedCountData:countData]];
	}
	self.cellDataArrays = arrays;
}

- (void)configureRoomBasedCountData:(RoomBasedCountData *)countData {
	countData.adultCount = MAX(MIN(self.minimumPeopleCount, self.maximumAdultCount), MAX(self.minimumAdultCount, 1));
	countData.childCount = MAX(MIN(self.minimumPeopleCount - countData.adultCount, self.maximumChildCount), 0);
	countData.infantCount = MAX(MIN(self.minimumPeopleCount - countData.adultCount - countData.childCount, self.maximumInfantCount), 0);
}

- (void)insertChildAgeIntoRoomBasedCountData:(RoomBasedCountData *)countData {
	[countData.childrenAge addObject:@(MAX(MIN(self.preferredChildAge, self.maximumChildAge), self.minimumChildAge))];
}

- (BOOL)validateCount {
	NSInteger totalPeopleCount = 0;
	for (RoomBasedCountData *countData in self.countDatas) {
		totalPeopleCount += countData.peopleCount;
		if (self.minimumPeopleCount > 0 && countData.peopleCount < self.minimumPeopleCount) {
			[CocoaUtils showAlertWithTitle:IMLocalizedString(@"Information") message:[NSString stringWithFormat:IMLocalizedString(@"Minimum Traveler Per Room is %d"), self.minimumPeopleCount] dismissalHandler:^{
				[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:countData.roomNo] atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
			}];
			return NO;
		}
		if (self.maximumPeopleCount > 0 && countData.peopleCount > self.maximumPeopleCount) {
			[CocoaUtils showAlertWithTitle:IMLocalizedString(@"Information") message:[NSString stringWithFormat:IMLocalizedString(@"Maximum Traveler Per Room is %d"), self.maximumPeopleCount] dismissalHandler:^{
				[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:countData.roomNo] atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
			}];
			return NO;
		}
	}
	if (self.maxPeople && totalPeopleCount > self.maxPeople) {
		[CocoaUtils showAlertWithTitle:IMLocalizedString(@"Information") message:[NSString stringWithFormat:@"Maximum Traveler count is %d", self.maxPeople] dismissalHandler:^{
		}];
		return NO;
	}
	if (self.peoleMinimum && totalPeopleCount < self.peoleMinimum) {
		[CocoaUtils showAlertWithTitle:IMLocalizedString(@"Information") message:[NSString stringWithFormat:@"Minimum Traveler count is %d", self.peoleMinimum] dismissalHandler:^{
		}];
		return NO;
	}
	return YES;
}

#pragma mark - Table view methods

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
	return self.cellDataArrays.count;
}

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

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
	if (section > 0) {
		NSMutableString *string = [NSMutableString string];
		[string im_appendString:IMLocalizedString(@"Room")];
		[string im_appendString:WORD_DIVIDER_SPACE];
		[string appendFormat:@"%d", section];
		return [NSString stringWithString:string];
	}
	return nil;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
	TableViewCellData *data = self.cellDataArrays[indexPath.section][indexPath.row];
	return [UIToolkit tableView:tableView atIndexPath:indexPath cellWithData: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
