//
// TourSearchOptionViewController.m
// IvyMedia
//
// Created by haibara on 9/22/14.
//
//

#import "TourSearchOptionViewController.h"
#import "Lang.h"
#import "SDK.h"
#import "CocoaUtils.h"
#import "CalendarViewController.h"
#import "DrawUtils.h"
#import "TextViewController.h"
#import "UIConstants.h"
#import "UIToolkit.h"
#import <BlocksKit/BlocksKit.h>
#import <BlocksKit/BlocksKit+UIKit.h>
#import <BlocksKit/A2DynamicDelegate.h>
#import <BlocksKit/NSObject+A2DynamicDelegate.h>
#import <libextobjc/EXTScope.h>
#import <PureLayout/PureLayout.h>
#import <YYModel/YYModel.h>
#import "Utility.h"
#import "AppTracker.h"
#import "FlightInfo.h"
#import "SalesEntryRoom.h"
#import "SoldStock.h"
#import "CheckAvailabilityAndPricesResponseJsonMapper.h"
#import "FlightInfoViewController.h"
#import "PPLBasedCountViewController.h"
#import "RoomBasedCountViewController.h"
#import "PerlWS.h"
#import "GetTourOptionsResponseJsonMapper.h"
#import "BookingReviewViewController.h"
#import "SelectLocationViewController.h"
#import "Vars.h"
#import "TourOptionViewController.h"
#import "RoomBasedPrice.h"
#import "TourSearchOptionCell.h"
#import "BusSearchDetailPriceView.h"
#import "CocoaUtils.h"

NSString *const DateCellIdentifier = @"DateCellIdentifier";

@interface TourSearchOptionViewController ()
@property (nonatomic, strong) CheckAvailabilityAndPricesResponse *checkAvailabilityAndPricesResponse;
@property (nonatomic, strong) NSMutableArray *cellDataArrays;
@property (nonatomic, strong) NSArray *availableDates;
@property (nonatomic, strong) NSMutableDictionary *errorDic;
@property (nonatomic, strong) NSString *depatureTimeString;
@property (nonatomic, strong) UIStackView *stackView;
@property (nonatomic, strong) UIButton *addToCartButton;
@property(nonatomic, assign) BOOL isErrorMessageAlerted;
@end

@implementation TourSearchOptionViewController

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

- (void)viewDidLoad {
	[super viewDidLoad];

	[[AppTracker sharedInstance] sendView:[self class]];
	self.errorDic = [NSMutableDictionary dictionary];
	self.checkAvailabilityAndPricesResponse = [[CheckAvailabilityAndPricesResponse alloc] init];

	@weakify(self)
	self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] bk_initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh handler:^(id sender) {
		@strongify(self)
		[self getTourPrice: NO];
	}];
	[self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([TourSearchOptionCell class]) bundle:nil] forCellReuseIdentifier:NSStringFromClass([TourSearchOptionCell class])];
	if (YES) {
		UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth([UIScreen mainScreen].bounds), 55)];
		footerView.backgroundColor = [UIColor whiteColor];
		
		UIStackView *contentView = [[UIStackView alloc] initWithFrame:footerView.frame];
		contentView.tag = NSStringFromClass([UIStackView class]).hash;
		contentView.axis = UILayoutConstraintAxisHorizontal;
		contentView.alignment = UIStackViewAlignmentCenter;
		contentView.distribution = UIStackViewDistributionFill;
		contentView.spacing = 15;
		if ([CocoaUtils isIPhoneX]) {
			contentView.frame = CGRectSetWidth(contentView.frame, CGRectGetWidth(contentView.frame) - 15);
		}
		[footerView addSubview:contentView];
		
		BusSearchDetailPriceView *view = [BusSearchDetailPriceView viewFromNib];
		view.titleLabel.textColor = [UIColor blackColor];
		view.subtitleLabel.textColor = [CocoaUtils colorWithRGBs:0x999999];
		view.titleLabel.text = @"Total Fares:";
		view.subtitleLabel.text = IMLocalizedString(@"(incl. tax and fees)");
		view.detailDisclosureButton.hidden = YES;
		[contentView addArrangedSubview:view];
		
		UILabel *priceLabel = [[UILabel alloc] init];
		priceLabel.attributedText = [self priceString];
		priceLabel.font = [UIFont boldSystemFontOfSize:24];
		[contentView addArrangedSubview:priceLabel];
		
		UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
		button.backgroundColor = [Vars defaultTintColor];
		button.titleLabel.font = [UIFont boldSystemFontOfSize:16];
		[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
		[button setTitleColor:[CocoaUtils colorWithRGBs:0xa4c1ff] forState:UIControlStateDisabled];
		[button setTitle:IMLocalizedString(@"Add to Cart") forState:UIControlStateNormal];
		[button autoSetDimension:ALDimensionWidth toSize:120];
		[button autoSetDimension:ALDimensionHeight toSize:55 - 2 * ([CocoaUtils isIPhoneX] ? 5 : 0)];
		[button addTarget:self action:@selector(addToCart) forControlEvents:UIControlEventTouchUpInside];
		if ([CocoaUtils isIPhoneX]) {
			[Utility addRoundedBorderToButton:button];
		}
		self.addToCartButton = button;
		self.addToCartButton.enabled = NO;
		[contentView addArrangedSubview:button];
		self.stackView = contentView;
		self.fixedFooterView = footerView;
	}
	self.tableView.estimatedRowHeight = 55;
	self.tableView.separatorColor = [CocoaUtils colorWithRGBs:0xebebeb];
	self.tableView.sectionHeaderHeight = [UIConstants defaultTableViewCellLayoutInsets].top;
	self.tableView.sectionFooterHeight = [UIConstants defaultTableViewCellLayoutInsets].bottom;
	[self buildCellDataSource];
}

- (void)viewDidAppear:(BOOL)animated {
	[super viewDidAppear:animated];
	
	[[Vars appDelegate].shopCarts.entries removeAllObjects];
	// ajax
	if (self.entry.product.labels.count <= 1) {
		[self getTourOptions];
	}
}

#pragma mark - Action

- (void)addToCart {
	if (![self validateCheckAvailabilityAndPricesResponse]) {
		return;
	}
	if (![self validateTourOptions:NO]) {
		return;
	}
	for (CartEntry *entry in @[self.entry]) {
		for (SoldStock *stock in entry.serialStocks) {
			if ([StringUtils isEmpty:stock.gender] && entry.product.need_gender) {
				stock.gender = @"Mr.";
			}
			if (!stock.passport && entry.product.is_need_passport) {
				if (entry.product.is_distinguish_passport) {
					stock.passport = [[Passport alloc] initAsDistinguish];
				} else {
					stock.passport = [[Passport alloc] init];
				}
			}
		}
	}
	[[Vars appDelegate].shopCarts.entries addObject:self.entry];

	BookingReviewViewController *viewController = [[BookingReviewViewController alloc] init];
	viewController.checkAvailabilityAndPricesResponse = self.checkAvailabilityAndPricesResponse;
	[self.navigationController pushViewController:viewController animated:YES];
}

#pragma mark - Segue

- (void)performSegueForPeopleBasedWithLabel:(GetTourOptionsResponseLabel *)label onTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath {
	if ([label.type isEqualToString:@"room_based"]) {
		RoomBasedCountViewController *viewController = [[RoomBasedCountViewController alloc] initWithRoomBasedCountDatas:self.entry.roomBasedCountDatas];
		[viewController setPropertiesWithRoomBasedPrice:self.entry.product.roomBasedPrice];
		[viewController setDidCancelBlock:^{
			[self.navigationController popViewControllerAnimated:YES];
		}];
		[viewController setDidDoneBlock:^(NSArray *countDatas) {
			[self.navigationController popViewControllerAnimated:YES];
			if (![self.entry.roomBasedCountDatas isEqualToArray:countDatas]) {
				self.entry.roomBasedCountDatas = countDatas;
				[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
				[self getTourPrice];
			}
			[self numberOfPeopleHasConflictWithOption];
		}];
		[self.navigationController pushViewController:viewController animated:YES];
	} else if ([label.type isEqualToString:@"ppl_based"]) {
		PPLBasedCountViewController *viewController = [[PPLBasedCountViewController alloc] initWithPPLBasedCountData:self.entry.PPLBasedCountData];
		[viewController setPropertiesWithPPLBasedPrice:self.entry.product.PPLBasedPrice];
		[viewController setDidCancelBlock:^{
			[self.navigationController popViewControllerAnimated:YES];
		}];
		[viewController setDidDoneBlock:^(PPLBasedCountData *countData) {
			[self.navigationController popViewControllerAnimated:YES];
			if (![self.entry.PPLBasedCountData isEqual:countData]) {
				self.entry.PPLBasedCountData = countData;
				[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
				[self getTourPrice];
			}
			[self numberOfPeopleHasConflictWithOption];
		}];
		[self.navigationController pushViewController:viewController animated:YES];
	}
}

- (void)performSegueForFlightInfoWithLabel:(GetTourOptionsResponseLabel *)label onTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath {
	FlightInfo *flightInfo = self.entry.options[label.alias];
	if (!flightInfo) {
		flightInfo = [[FlightInfo alloc] init];
	}
	FlightInfoViewController *viewController = [[FlightInfoViewController alloc] initWithFlightInfo:flightInfo];
	viewController.title = label.name;
	viewController.readonly = NO;
	viewController.allowIfAdvisedWhileEditing = YES;
	viewController.arrivalAirportOptions = label.arrivalAirportOptions;
	viewController.returnAirportOptions = label.returnAirportOptions;
	[viewController setDidCancelBlock:^{
		[self.navigationController popViewControllerAnimated:YES];
	}];
	[viewController setDidDoneBlock:^(FlightInfo *flightInfo) {
		[self.navigationController popViewControllerAnimated:YES];
		if (![flightInfo isEqual:self.entry.options[label.alias]]) {
			self.entry.options[label.alias] = flightInfo;
			[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
			[self getTourPrice];
		}
	}];
	[self.navigationController pushViewController:viewController animated:YES];
}

- (void)performSegueForTextareaWithLabel:(GetTourOptionsResponseLabel *)label onTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath {
	TextViewController *viewController = [[TextViewController alloc] init];
	viewController.title = label.name;
	[[Vars appDelegate] applyDefaultConfigurationForViewController:viewController];
	viewController.textView.editable = YES;
	if (![StringUtils isBlank:self.entry.options[label.alias]]) {
		viewController.textView.text = self.entry.options[label.alias];
	} else {
		[viewController.textView becomeFirstResponder];
	}
	if (label.isTypeAsInput) {
		viewController.isSingleLine = YES;
	}
	viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] im_initWithBarButtonSystemItem:UIBarButtonSystemItemCancel handler:^(UIBarButtonItem *barButtonItem) {
		[self.navigationController popViewControllerAnimated:YES];
	}];
	@weakify(viewController)
	viewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] im_initWithBarButtonSystemItem:UIBarButtonSystemItemDone handler:^(UIBarButtonItem *barButtonItem) {
		[self.navigationController popViewControllerAnimated:YES];
		@strongify(viewController)
		NSString *text = viewController.textView.text;
		if (![text isEqualToString:self.entry.options[label.alias]]) {
			self.entry.options[label.alias] = text;
			[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
			[self getTourPrice];
		}
	}];
	[self.navigationController pushViewController:viewController animated:YES];
}

- (void)performSegueForBusStopWithLabel:(GetTourOptionsResponseLabel *)label onTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath {
	SelectLocationViewController *viewController = [[SelectLocationViewController alloc] init];
	viewController.title = label.name;
	[[Vars appDelegate] applyDefaultConfigurationForViewController:viewController];
	for (GetTourOptionsResponseLocationTuple *tuple in label.currentTuples) {
		[viewController addAnnotations:[BusStop toAnnotations:tuple.stations] title:tuple.station_city_name];
	}
	if (![StringUtils isEmpty:self.entry.options[label.alias]]) {
		[viewController selectAnnotation:[[viewController getAnnotations] bk_match:^BOOL (MapViewAnnotation *annotation) {
			return [self.entry.options[label.alias] isEqualToString:annotation.value];
		}]];
	}
	[viewController setDidCancelBlock:^{
		[self.navigationController popViewControllerAnimated:YES];
	}];
	[viewController setDidDoneBlock:^(MapViewAnnotation *annotation) {
		[self.navigationController popViewControllerAnimated:YES];
		if (![annotation.value isEqualToString:self.entry.options[label.alias]] && ![StringUtils isEmpty:annotation.value]) {
			self.entry.options[label.alias] = annotation.value;
			[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
			[self getTourPrice];
		}
	}];
	[self.navigationController pushViewController:viewController animated:YES];
}

- (void)performSegueForDateWithLabel:(GetTourOptionsResponseLabel *)label onTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath {
	CalendarViewController *viewController = [[CalendarViewController alloc] init];
	viewController.title = label.name;
	[[Vars appDelegate] applyDefaultConfigurationForViewController:viewController];
	viewController.calendarManager.minimumDate = self.availableDates.firstObject;
	viewController.calendarManager.maximumDate = self.availableDates.lastObject;
	viewController.calendarManager.enabledDates = self.availableDates;
	[viewController.calendarManager setDidSelectDateBlock:^(NSDate *date) {
		[self.navigationController popViewControllerAnimated:YES];
		Label *label = [self.entry.product.labels bk_match:^BOOL (Label *obj) {
			return obj.isKindOfDate;
		}];
		if ([self.availableDates containsObject:date]) {
			self.entry.options[@"date"] = label.options[[self.availableDates indexOfObject:date]];
		}
		[self depatureDateConfict:YES];
		[self.tableView reloadData];
		[self getTourPrice];
	}];
	if (![StringUtils isEmpty:self.entry.options[label.alias]]) {
		[viewController selectDate:[[DateFormatUtils ISO_DATE_FORMAT] parse:[self.entry.options[label.alias] substringToIndex:10]]];
	}
	[self.navigationController pushViewController:viewController animated:YES];
}

-(void)performSegueOptionViewControllerWith:(GetTourOptionsResponseLabel *)label withIndexPath:(NSIndexPath *)indexPath{
	TourOptionViewController *viewController = [[TourOptionViewController alloc] init];
	if (!label.entries.count && label.options.count) {
		NSMutableArray *entryArray = [NSMutableArray array];
		[label.options bk_each:^(NSString * option) {
			if (![StringUtils isEmpty:option]) {
				LabelEntry *entry = [[LabelEntry alloc] init];
				entry.value = option;
				[entryArray addObject:entry];
			}
		}];
		label.entries = entryArray;
	}
	for (LabelEntry *entry in label.entries) {
		entry.isAvailable = [self depatureDateHasConflictWithOption:entry] ? NO : YES;
		for (Formula *formula in entry.formulas) {
			formula.isShow = [self depatureDateHasConfictWithFormula:formula] ? NO : YES;
		}
		if ([self depatureDateHasConflictWithOption:entry]) {
			entry.isChecked = NO;
		}
	}
	if (label.entries.count == 1) {
		LabelEntry *entry = label.entries.firstObject;
		entry.isChecked = YES;
	}
	viewController.labelString = [label yy_modelToJSONString];
	viewController.optionTitle = label.name;
	viewController.indexBlock = ^(NSInteger index) {
		LabelEntry *entry = label.entries[index];
		if ([self depatureDateHasConflictWithOption:entry]) {
			self.entry.options[label.alias] = entry.value;
			[self depatureDateConfict:NO];
			[self.tableView reloadData];
			return ;
		}
		
		if (![entry.value isEqual:self.entry.options[label.alias]]) {
			self.entry.options[label.alias] = entry.value;
			[label.entries bk_each:^(LabelEntry *  entry) {
				entry.isChecked = NO;
			}];
			entry.isChecked = YES;
			self.errorDic = [NSMutableDictionary dictionary];
			[self numberOfPeopleHasConflictWithOption];
			[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
			[self getTourPrice];
		}
	};
	[self.navigationController pushViewController:viewController animated:YES];
}

#pragma mark - Network

- (void)checkAvailabilityAndPrices {
	if (self.checkAvailabilityAndPricesResponse) {
		self.checkAvailabilityAndPricesResponse = nil;
		[self reloadFixedFooterView];
	}
	
	CheckAvailabilityAndPrices *checkAvailabilityAndPrices = [[CheckAvailabilityAndPrices alloc] init];
	checkAvailabilityAndPrices.travelerDetails = [WebService travelerDetailsWithCartEntries:@[self.entry]];

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

	[Utility getXMLFromRequestWithMethod:@"POST" url:checkAvailabilityAndPrices.address parameters:requestDict success:^(NSString *xml) {
		NSString *responseStr = xml;
		// NSLog(@"%@", responseStr);
		CheckAvailabilityAndPricesResponseJsonMapper *mapper = [[CheckAvailabilityAndPricesResponseJsonMapper alloc] init];
		NSDictionary *jsonDict = [Utility JSONObjectWithXMLString:responseStr objectMapping:mapper.objectMapping];
		if (![mapper parseWithJSONObject:jsonDict]) {
			CheckAvailabilityAndPricesResponse *response = mapper.response;
			if (response.error_code > 0 && !self.isErrorMessageAlerted) {
				self.isErrorMessageAlerted = YES;
				[CocoaUtils showAlertWithTitle:IMLocalizedString(@"Error") message:response.error_message dismissalHandler:^{
					self.isErrorMessageAlerted = NO;
				}];
			} else {
				self.checkAvailabilityAndPricesResponse = response;
				[self reloadFixedFooterView];
			}
		}
	}];
}

- (void)getTourOptions {
	GetTourOptions *getTourOptions = [[GetTourOptions alloc] init];
	getTourOptions.tourCode = self.entry.product.tour_code;

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

	[Utility getXMLFromRequestWithMethod:@"GET" url:getTourOptions.address parameters:requestDict success:^(NSString *xml) {
		NSString *responseStr = xml;
		// NSLog(@"%@", responseStr);
		GetTourOptionsResponseJsonMapper *mapper = [[GetTourOptionsResponseJsonMapper alloc] init];
		NSDictionary *jsonDict = [Utility JSONObjectWithXMLString:responseStr objectMapping:mapper.objectMapping];
		// NSLog(@"%@", jsonDict);
		if (![mapper parseWithJSONObject:jsonDict]) {
			GetTourOptionsResponse *response = mapper.response;
			if (response.error_code > 0) {
				[CocoaUtils showAlertWithTitle:IMLocalizedString(@"Error") message:response.error_message];
			} else {
				self.entry.product.is_room_based = response.needRoom;
				if (response.labels.count > 0) {
					GetTourOptionsResponseLabel *label = [[GetTourOptionsResponseLabel alloc] init];
					if (self.entry.product.is_room_based) {
						label.type = @"room_based";
						label.name = IMLocalizedString(@"Number of Rooms");
					} else {
						label.type = @"ppl_based";
						label.name = IMLocalizedString(@"Number of People");
					}
					self.entry.product.labels = [ArrayUtils add:response.labels index:1 element:label];
				}
				if (self.entry.product.is_room_based) {
					self.entry.product.roomBasedPrice = [[RoomBasedPrice alloc] init];
					for (GetProductOptionsResponsePeopleType *peopleType in response.peopleTypes) {
						if ([peopleType.name isEqualToString:@"child"]) {
							self.entry.product.roomBasedPrice.enable_child = YES;
						} else if ([peopleType.name isEqualToString:@"infant"]) {
							self.entry.product.roomBasedPrice.enable_infant = YES;
						}
					}
					if (response.limitPeopleNumberOfRoom) {
						self.entry.product.roomBasedPrice.min_people_num = response.limitPeopleNumberOfRoom.minPeople;
						self.entry.product.roomBasedPrice.max_people_num = response.limitPeopleNumberOfRoom.maxPeople;
						self.entry.product.roomBasedPrice.min_adult_num = response.limitPeopleNumberOfRoom.minAdult;
						self.entry.product.roomBasedPrice.max_adult_num = response.limitPeopleNumberOfRoom.maxAdult;
						self.entry.product.roomBasedPrice.max_child_num = response.limitPeopleNumberOfRoom.maxChild;
						self.entry.product.roomBasedPrice.max_infant_num = response.limitPeopleNumberOfRoom.maxInfant;
						self.entry.product.roomBasedPrice.peopleMinimum = response.peopleMinimum;
						self.entry.product.roomBasedPrice.maxPeople = response.maxPeople;
					}
					RoomBasedCountData *countData = [[RoomBasedCountData alloc] initWithRoomNo:1];
					[countData configureWithRoomBasedPrice:self.entry.product.roomBasedPrice];
					self.entry.roomBasedCountDatas = @[countData];
				} else {
					self.entry.product.PPLBasedPrice = [[PPLBasedPrice alloc] init];
					for (GetProductOptionsResponsePeopleType *peopleType in response.peopleTypes) {
						if ([peopleType.name isEqualToString:@"child"]) {
							self.entry.product.PPLBasedPrice.enable_child = YES;
							self.entry.product.PPLBasedPrice.child_age_from = peopleType.ageFrom;
							self.entry.product.PPLBasedPrice.child_age_to = peopleType.ageTo;
						} else if ([peopleType.name isEqualToString:@"infant"]) {
							self.entry.product.PPLBasedPrice.enable_infant = YES;
						} else if ([peopleType.name isEqualToString:@"senior"]) {
							self.entry.product.PPLBasedPrice.enable_senior = YES;
						} else if ([peopleType.name isEqualToString:@"junior"]) {
							self.entry.product.PPLBasedPrice.enable_junior = YES;
						} else if ([peopleType.name isEqualToString:@"student"]) {
							self.entry.product.PPLBasedPrice.enable_student = YES;
						} else if ([peopleType.name isEqualToString:@"soldier"]) {
							self.entry.product.PPLBasedPrice.enable_soldier = YES;
						}
					}
					self.entry.product.PPLBasedPrice.min_people_num = response.peopleMinimum;
					PPLBasedCountData *countData = [[PPLBasedCountData alloc] init];
					[countData configureWithPPLBasedPrice:self.entry.product.PPLBasedPrice];
					self.entry.PPLBasedCountData = countData;
				}
				for (GetTourOptionsResponseLabel *label in self.entry.product.literalLabels) {
					if (label.isKindAsStop) {
						if (label.currentTuples.count == 1) {
							GetTourOptionsResponseLocationTuple *tuple = label.departs.firstObject;
							if (tuple.stations.count == 1) {
								BusStop *stop = tuple.stations.firstObject;
								self.entry.options[label.alias] = stop.option_value;
							}
						}
					} else if (label.options && label.options.count == 1) {
						self.entry.options[label.alias] = label.options.firstObject;
					}
					if (label.isKindOfDate) {
						self.availableDates = [label.options bk_map:^id (NSString *obj) {
							return [[DateFormatUtils ISO_DATE_FORMAT] parse:[obj substringToIndex:10]];
						}];
					}
				}
				[self buildCellDataSource];
				[self reloadFixedFooterView];
				[self.tableView reloadData];
				[self getTourPrice];
			}
		}
	}];
}

#pragma mark - Private

- (void)buildCellDataSource {
	@weakify(self)
	self.cellDataArrays = [NSMutableArray array];
	NSMutableArray *array = [NSMutableArray array];
	for (GetTourOptionsResponseLabel *label in self.entry.product.presaleLabels) {
		TableViewCellData *data = [[TableViewCellData alloc] init];
		data.usesAutomaticDimension = YES;
		data.isCustomRegistered = YES;
		data.reuseIdentifier = NSStringFromClass([TourSearchOptionCell class]);
		data.validationMessageCaption = label.name;
		if (label.isTypeAsPeopleBased) {
			[data setPostInstallBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data, TourSearchOptionCell *cell) {
				cell.titleText = label.name;
				cell.contentText = self.entry.shortDescription;
				cell.accessoryImageView.hidden = NO;
			}];
			[data setDidSelectBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data) {
				@strongify(self)
				[self performSegueForPeopleBasedWithLabel: label onTableView:tableView atIndexPath: indexPath];
			}];
		}else if (label.isTypeOfFlightInfo){
			[data setPostInstallBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data, TourSearchOptionCell *cell) {
				FlightInfo *flightInfo = self.entry.options[label.alias];
				cell.titleText = label.name;
				if (flightInfo) {
					cell.contentText = flightInfo.shortDescription;
					cell.allowContentWrapping = YES;
				}
				cell.accessoryImageView.hidden = NO;
			}];
			[data setDidSelectBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data) {
				@strongify(self)
				[self performSegueForFlightInfoWithLabel: label onTableView:tableView atIndexPath: indexPath];
			}];
			[data setVaryingHeightIdentifierBlock:^NSString *(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data){
				@strongify(self)
				FlightInfo *flightInfo = self.entry.options[label.alias];
				return [NSString stringWithFormat:@"%d", (flightInfo.is_to_be_advised ? 1 : 0) + (flightInfo.arrival_airport ? 1 : 0) + (flightInfo.return_airport ? 1 : 0)];
			}];
			if (label.required) {
				[data setRequiredValidationRuleBlock:^BOOL {
					@strongify(self)
					FlightInfo *flightInfo = self.entry.options[label.alias];
					return ![StringUtils isEmpty:flightInfo.shortDescription];
				}];
			}
		}else if(label.isKindOfTime){
			[data setPostInstallBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data, TourSearchOptionCell *cell) {
				cell.titleText = label.name;
				cell.contentText = self.entry.options[label.alias];
				cell.accessoryImageView.hidden = YES;
			}];
			data.editingType = TableViewCellEditingTypeDatePicker;
			[data setDatePickerMode:UIDatePickerModeTime];
			data.observedObject = self;
			data.keyPath = @"depatureTimeString";
			NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
			[dateFormatter setDateFormat:@"KK:mm aa"];
			data.outputDateFormatter = dateFormatter;
			data.inputDateFormatter = dateFormatter;
			[data setValueChangedPostActionBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data, id editingControl) {
				@strongify(self)
				self.entry.options[label.alias] = self.depatureTimeString;
				[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
				[self getTourPrice];
			}];
			if (label.required) {
				[data setRequiredValidationRuleBlock:^BOOL {
					@strongify(self)
					return ![StringUtils isEmpty:self.entry.options[label.alias]];
				}];
			}
		}else{
			[data setPostInstallBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data, TourSearchOptionCell *cell) {
				cell.titleText = label.name;
				cell.contentText = self.entry.options[label.alias];
				cell.accessoryImageView.hidden = NO;
			}];
			if (label.required) {
				if (label.isTypeOfText ) {
					[data setRequiredValidationRuleBlock:^BOOL {
						@strongify(self)
						return ![StringUtils isBlank:self.entry.options[label.alias]];
					}];
				} else {
					[data setRequiredValidationRuleBlock:^BOOL {
						@strongify(self)
						return ![StringUtils isEmpty:self.entry.options[label.alias]];
					}];
				}
			}
			if(label.isKindAsStop){
				if ([label.currentTuples bk_all:^BOOL (GetTourOptionsResponseLocationTuple *tuple) {
					return ![StringUtils isEmpty:tuple.station_city_name];
				}]) {
					[data setAccessoryViewBlock:^UIView *(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data){
						return [[UIImageView alloc] initWithImage:[DrawUtils imageWithFAKIcon:[FAKFontAwesome mapMarkerIconWithSize:24] fillColor:[UIColor lightGrayColor]]];
					}];
					[data setDidSelectBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data) {
						@strongify(self)
						[self performSegueForBusStopWithLabel: label onTableView:tableView atIndexPath: indexPath];
					}];
				} else {
					[data setDidSelectBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data) {
						@strongify(self)
						[self performSegueOptionViewControllerWith:label withIndexPath:indexPath];
					}];
				}
				[data addIntegrityValidationRuleBlock:^BOOL {
					@strongify(self)
					if (self.entry.options[@"date"] && self.entry.options[label.alias]) {
						return [self validateAvailableWithLabelOfStop:label];
					}
					return YES;
				} withMessageBlock:nil];
				[data setPostInstallBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data, TourSearchOptionCell *cell) {
					cell.titleText = label.name;
					cell.contentText = self.entry.options[label.alias];
					cell.accessoryImageView.hidden = YES;
				}];
			}else if (label.isKindOfDate){
				[data setPostInstallBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data, TourSearchOptionCell *cell) {
					cell.titleText = label.name;
					cell.contentText = self.entry.options[label.alias];
					cell.errorText =  self.errorDic[@"date"];
				}];
				[data setDidSelectBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data) {
					@strongify(self)
					[self performSegueForDateWithLabel: label onTableView:tableView atIndexPath: indexPath];
				}];
				data.identifier = DateCellIdentifier;
			}else if (label.options || label.entries.count) {
				[data setPostInstallBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data, TourSearchOptionCell *cell) {
					cell.titleText = label.name;
					cell.contentText = self.entry.options[label.alias];
					cell.errorText = self.errorDic[label.name];
				}];
				[data setDidSelectBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data) {
					@strongify(self)
					[self performSegueOptionViewControllerWith:label withIndexPath:indexPath];
				}];
				[data addIntegrityValidationRuleBlock:^BOOL {
					@strongify(self)
					for (LabelEntry *entry in label.entries) {
						if ([self.entry.options[label.alias] isEqualToString:entry.value] &&  [self depatureDateHasConflictWithOption:entry]) {
							self.errorDic[label.name] = [NSString stringWithFormat:IMLocalizedString(@"The selected option is not avaliable on %@.Please choose a different one."),self.entry.options[@"date"]];
							return NO;
						}
					}
					return YES;
				} withMessageBlock:nil];
			} else {
				[data setDidSelectBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data) {
					@strongify(self)
					[self performSegueForTextareaWithLabel: label onTableView:tableView atIndexPath: indexPath];
				}];
				[data addIntegrityValidationRuleBlock:^BOOL {
					@strongify(self)
					return [Utility canBeConvertedToUrlEncodedFromString:self.entry.options[label.alias]];
				} withMessageBlock:^NSString *{
					return IMLocalizedString(@"Please enter alphabetic characters only");
				}];
			}
		}
		[array addObject:data];
	}
	self.cellDataArrays = [NSArray arrayWithArray:array];
}

- (void)getTourPrice {
	[self getTourPrice:YES];
}

- (void)getTourPrice:(BOOL)slient {
	if ([self validateTourOptions:slient]) {
		[self checkAvailabilityAndPrices];
	}
}

- (BOOL)validateAvailableWithLabelOfStop:(GetTourOptionsResponseLabel *)label {
	NSArray *stops = [label.currentTuples valueForKeyPath:@"@unionOfArrays.stations"];
	BusStop *stop = [stops bk_match:^BOOL (BusStop *stop) {
		return [stop.option_value isEqualToString:self.entry.options[label.alias]];
	}];
	if (stop) {
		return [stop checkAvailable:[self.entry.options[@"date"] substringToIndex:10]];
	}
	return YES;
}

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

- (BOOL)validateCheckAvailabilityAndPricesResponse {
	if (self.isErrorMessageAlerted) {
		return NO;
	}
	if (self.checkAvailabilityAndPricesResponse.error_code > 0) {
		[CocoaUtils showAlertWithTitle:IMLocalizedString(@"Error") message:self.checkAvailabilityAndPricesResponse.error_message];
		return NO;
	}
	if (self.checkAvailabilityAndPricesResponse.total_charge <= 0) {
		[CocoaUtils showAlertWithTitle:IMLocalizedString(@"Error") message:[Vars responseException]];
		return NO;
	}
	BOOL hasHotel = [[Vars appDelegate].shopCarts.entries bk_any:^BOOL (CartEntry *obj) {
		return obj.product.is_hotel;
	}];
	if (hasHotel && self.checkAvailabilityAndPricesResponse.entries.count != [Vars appDelegate].shopCarts.entries.count) {
		[CocoaUtils showAlertWithTitle:IMLocalizedString(@"Error") message:[Vars responseException]];
		return NO;
	}
	return YES;
}

- (void)reloadTableViewCellByIdentifier:(NSString *)cellIdentifier {
	NSIndexPath *indexPath = [CocoaUtils indexPathOfObjectIdenticalTo:[CocoaUtils objectPassingTest:^BOOL(TableViewCellData *obj, NSUInteger idx, BOOL *stop) {
		return [obj.identifier isEqualToString:cellIdentifier];
	} fromArray:self.cellDataArrays] fromArray:self.cellDataArrays inSection:0];
	if (indexPath) {
		[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
	}
}

-(BOOL)depatureDateHasConflictWithOption:(LabelEntry *)entry{
	NSString *optionsDateString = self.entry.options[@"date"];
	if (optionsDateString && entry.dateString) {
		optionsDateString =	[optionsDateString substringToIndex:10];
		if (![entry.dateString containsString:optionsDateString]) {
			return YES;
		}
	}
	return NO;
}

-(BOOL)depatureDateHasConfictWithFormula:(Formula *)formula{
	NSString *formulaDateString = self.entry.options[@"date"];
	if (formulaDateString && formula.dateString) {
		formulaDateString = [formulaDateString substringToIndex:10];
		if (![formula.dateString containsString:formulaDateString]) {
			return YES;
		}
	}
	return NO;
}


-(void)depatureDateConfict:(BOOL)depatureDate{
	self.errorDic = [NSMutableDictionary dictionary];
	for (GetTourOptionsResponseLabel *label in self.entry.product.presaleLabels) {
		if (label.options || label.entries) {
			for (LabelEntry *entry in label.entries) {
				if ([self depatureDateHasConflictWithOption:entry]) {
					if (self.checkAvailabilityAndPricesResponse) {
						self.checkAvailabilityAndPricesResponse = nil;
						[self reloadFixedFooterView];
					}
					if (depatureDate && [self.entry.options[label.alias] isEqualToString:entry.value]) {
						self.errorDic[label.name] = [NSString stringWithFormat:IMLocalizedString(@"The selected option is not avaliable on %@. Please choose a different one."),self.entry.options[@"date"]];
					}else if (!depatureDate){
						self.errorDic[@"date"] = [NSString stringWithFormat:IMLocalizedString(@"The selected option is not avaliable on %@. Please re-select departure date."),self.entry.options[@"date"]];
						self.entry.options[@"date"] = nil;
					}
				}
			}
		}
	}
}

-(void)numberOfPeopleHasConflictWithOption{
	for (GetTourOptionsResponseLabel *label in self.entry.product.presaleLabels) {
		if (label.options || label.entries) {
			for (LabelEntry *entry in label.entries) {
				if ([self.entry.options[label.alias] isEqualToString:entry.value] && entry.minPeople > self.entry.peopleCount) {
					if (self.isErrorMessageAlerted) {
						return;
					}
					if (self.checkAvailabilityAndPricesResponse) {
						self.checkAvailabilityAndPricesResponse = nil;
						[self reloadFixedFooterView];
					}
					self.isErrorMessageAlerted = YES;
					[CocoaUtils showAlertWithTitle:IMLocalizedString(@"Error") message:[NSString stringWithFormat:IMLocalizedString(@"A minimum of %@ passengers are required to book %d. Please adjust your group size or select other avaliable options."),entry.value,entry.minPeople] dismissalHandler:^{
						self.isErrorMessageAlerted = NO;
					}];
				}
			}
		}
	}
}

- (void)reloadFixedFooterView {
	self.addToCartButton.enabled = NO;
	UILabel *priceLabel = self.stackView.arrangedSubviews[1];
	if (self.checkAvailabilityAndPricesResponse && self.checkAvailabilityAndPricesResponse.total_charge > 0 ){
		self.addToCartButton.enabled = YES;
	}
	priceLabel.attributedText = [self priceString];
}

//拆分浮点数
-(NSAttributedString *)priceString{
	NSString *priceString = [NSString stringWithFormat:@"%g",self.checkAvailabilityAndPricesResponse.total_charge];
	NSArray *priceArray = [priceString componentsSeparatedByString:@"."];
	NSMutableAttributedString *priceAttributeString = [[NSMutableAttributedString alloc] init];
	NSAttributedString *symbolAttributedString = [[NSAttributedString alloc] initWithString:@"$" attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16],NSForegroundColorAttributeName :[CocoaUtils colorWithRGBs:StandardColorOrange]}];
	if (priceArray.count > 1) {
		NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:priceArray[0] attributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:24],NSForegroundColorAttributeName :[CocoaUtils colorWithRGBs:StandardColorOrange]}];
		NSAttributedString *dotAttributedString = [[NSAttributedString alloc] initWithString:@"." attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16],NSForegroundColorAttributeName :[CocoaUtils colorWithRGBs:StandardColorOrange]}];
		NSAttributedString *decimalAttributedString = [[NSAttributedString alloc] initWithString:priceArray[1] attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16],NSForegroundColorAttributeName :[CocoaUtils colorWithRGBs:StandardColorOrange]}];
		[priceAttributeString appendAttributedString:symbolAttributedString];
		[priceAttributeString appendAttributedString:attributedString];
		[priceAttributeString appendAttributedString:dotAttributedString];
		[priceAttributeString appendAttributedString:decimalAttributedString];
	}else{
		NSAttributedString *attributedString0 = [[NSAttributedString alloc] initWithString:priceString attributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:24],NSForegroundColorAttributeName :[CocoaUtils colorWithRGBs:StandardColorOrange]}];
		[priceAttributeString appendAttributedString:symbolAttributedString];
		[priceAttributeString appendAttributedString:attributedString0];
	}
	return priceAttributeString;
}

#pragma mark - Table view methods

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

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

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
	if (section == 0) {
		return IMLocalizedString(@"Price a Trip, Book Now");
	}
	return nil;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
	if (section == 0) {
		UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 55)];
		UILabel *label = [[UILabel alloc] init];
		label.text = IMLocalizedString(@"Price a Trip, Book Now");
		label.textColor = [CocoaUtils colorWithRGBs:0x2f5db5];
		label.font = [UIFont boldSystemFontOfSize:17];
		[headerView addSubview:label];
		[label autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:16];
		[label autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:10];
		return headerView;
	}
	return nil;
}


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

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
	return UITableViewAutomaticDimension;
}

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

@end
