#import "SalesEntry.h"
#import "Lang.h"
#import "SDK.h"
#import "BeanUtils.h"
#import "CocoaUtils.h"
#import "UIConstants.h"
#import <BlocksKit/BlocksKit.h>
#import "Utility.h"
#import "Destination.h"
#import "Label.h"
#import "SalesEntryRoom.h"
#import "SoldStock.h"
#import "Vars.h"

@interface SalesEntry ()
@property (nonatomic, strong, readonly) BusStop *firstDepartureStop;
@property (nonatomic, strong, readonly) BusStop *lastArrivalStop;
@end

@implementation SalesEntry

#pragma mark - Public

- (BusStop *)firstDepartureStop {
	if (self.departureStops.count > 0) {
		return self.departureStops.firstObject;
	}
	return nil;
}

- (BusStop *)lastArrivalStop {
	if (self.arrivalStops.count > 0) {
		return self.arrivalStops.lastObject;
	}
	return nil;
}

- (BOOL)confirmed {
	return self.status == 5;
}

- (BOOL)cancelled {
	return self.status == 8;
}

- (NSArray *)serialStocks {
	NSArray *stocks = nil;
	if (self.rooms.count == 0) {
		stocks = self.stocks;
	} else {
		if (self.product.is_hotel) {
			stocks = [self.rooms valueForKeyPath:@"checkin_guest"];
		} else {
			stocks = [self.rooms valueForKeyPath:@"@unionOfArrays.stocks"];
		}
	}
	return stocks;
}

- (NSArray *)optionalLabels {
	return [self.product.labels bk_select:^BOOL (Label *label) {
		return [self hasOption:label.alias];
	}];
}

- (NSArray *)departureStops {
	return [[self.serialStocks valueForKeyPath:@"@distinctUnionOfObjects.departureStop"] sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"time_value" ascending:YES]]];
}

- (NSArray *)arrivalStops {
	return [[self.serialStocks valueForKeyPath:@"@distinctUnionOfObjects.arrivalStop"] sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"time_value" ascending:YES]]];
}

- (NSDate *)departureDate {
	return [[DateFormatUtils ISO_DATE_FORMAT] parse:self.service_date];
}

- (NSDate *)firstDepartureDate {
	if (self.firstDepartureStop && ![StringUtils isEmpty:self.firstDepartureStop.time_value]) {
		return [DateUtils parseDate:[NSString stringWithFormat:@"%@ %@", self.service_date, self.firstDepartureStop.time_value] parsePatterns:@"yyyy-MM-dd HH:mm", nil];
	}
	return nil;
}

- (NSArray *)datedDepartureStops {
	return [self.product.departureStops bk_select:^BOOL (BusStop *stop) {
		return [stop checkAvailable:self.service_date];
	}];
}

- (NSArray *)datedArrivalStops {
	return [self.product.arrivalStops bk_select:^BOOL (BusStop *stop) {
		return [stop checkAvailable:self.service_date];
	}];
}

- (NSString *)localizedDepartureDateString {
	if (self.firstDepartureDate) {
		return [CocoaUtils localizedStringFromDate:self.firstDepartureDate template:@"hmmaEEEMMMdyyyy"];
	} else {
		return [Utility localizedStringWithDate:self.departureDate];
	}
}

- (NSString *)calendarNote {
	NSString *stockText = nil;
	if (YES) {
		NSMutableArray *objs = [NSMutableArray array];
		if (self.rooms.count > 0) {
			for (SalesEntryRoom *room in self.rooms) {
				[objs addObject:room];
				if (!room.checkin_guest) {
					[objs addObjectsFromArray:room.stocks];
				}
			}
		} else {
			[objs addObjectsFromArray:self.stocks];
		}
		NSMutableArray *array = [NSMutableArray array];
		for (id obj in objs) {
			if ([obj class] == [SalesEntryRoom class]) {
				SalesEntryRoom *room = obj;
				[array addObject:room.shortDescription];
				if (self.product.is_hotel) {
					[array addObject:[self peopleDescriptionAtRoomNo:room.room_no]];
				}
				if (room.room_type) {
					NSMutableString *string = [NSMutableString string];
					[string im_appendString:IMLocalizedString(@"Room Type")];
					[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
					[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
					[string im_appendString:room.room_type];
					[array addObject:string];
				}
				if (room.check_in && room.check_out) {
					if (YES) {
						NSMutableString *string = [NSMutableString string];
						[string im_appendString:IMLocalizedString(@"Check-in Date")];
						[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
						[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
						[string im_appendString:[Utility localizedStringWithStandardDateString:room.check_in]];
						[array addObject:string];
					}
					if (YES) {
						NSMutableString *string = [NSMutableString string];
						[string im_appendString:IMLocalizedString(@"Check-out Date")];
						[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
						[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
						[string im_appendString:[Utility localizedStringWithStandardDateString:room.check_out]];
						[array addObject:string];
					}
					if (YES) {
						NSMutableString *string = [NSMutableString string];
						[string im_appendString:IMLocalizedString(@"Night(s)")];
						[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
						[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
						[string appendFormat:@"%d", room.nights];
						[array addObject:string];
					}
				}
				if (room.checkin_guest) {
					NSMutableString *string = [NSMutableString string];
					[string im_appendString:IMLocalizedString(@"Check-in Guest")];
					[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
					[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
					[string im_appendString:room.checkin_guest.hotelDescription];
					[array addObject:string];
				}
				if (room.reservation_number) {
					NSMutableString *string = [NSMutableString string];
					[string im_appendString:IMLocalizedString(@"Reservation Number")];
					[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
					[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
					[string im_appendString:room.reservation_number];
					[array addObject:string];
				}
				if (room.record_locator) {
					NSMutableString *string = [NSMutableString string];
					[string im_appendString:IMLocalizedString(@"Record Locator")];
					[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
					[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
					[string im_appendString:room.record_locator];
					[array addObject:string];
				}
			} else if ([obj class] == [SoldStock class]) {
				SoldStock *stock = obj;
				NSMutableString *string = [NSMutableString string];
				if (stock.sold_to_name) {
					[string im_appendString:stock.sold_to_name];
					[string im_appendString:IMLocalizedString(PUNCTUATION_COMMA)];
					[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
				}
				[string im_appendString:stock.otherLongDescription];
				[array addObject:string];
			}
		}
		if (array.count > 0) {
			stockText = [array componentsJoinedByString:@"\n"];
		}
	}
	NSString *optionText = nil;
	if (YES) {
		NSMutableArray *array = [NSMutableArray array];
		for (Label *label in self.optionalLabels) {
			NSMutableString *string = [NSMutableString string];
			[string im_appendString:label.name];
			[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
			[string im_appendString:@"\n"];
			[string im_appendString:[self getOptionText:label.alias]];
			[array addObject:string];
		}
		if (array.count > 0) {
			optionText = [array componentsJoinedByString:@"\n"];
		}
	}
	NSMutableString *string = [NSMutableString string];
	[string im_appendString:self.shortDescription];
	if (stockText) {
		[string im_appendString:@"\n"];
		[string im_appendString:stockText];
	}
	[string im_appendString:@"\n"];
	[string im_appendString:@"\n"];
	[string im_appendString:IMLocalizedString(@"Product")];
	[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
	[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
	[string im_appendString:self.product.name];
	if (!self.product.is_hotel) {
		[string im_appendString:@"\n"];
		[string im_appendString:IMLocalizedString(@"Departure Date")];
		[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
		[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
		[string im_appendString:self.localizedDepartureDateString];
	}
	if (optionText) {
		[string im_appendString:@"\n"];
		[string im_appendString:optionText];
	}
	[string im_appendString:@"\n"];
	[string im_appendString:@"\n"];
	[string im_appendString:IMLocalizedString(@"Itinerary ID")];
	[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
	[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
	[string im_appendString:self.itinerary_id];
	[string im_appendString:@"\n"];
	[string im_appendString:IMLocalizedString(@"Payment")];
	[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
	[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
	[string appendFormat:@"$%g", self.sold_amount];
	[string im_appendString:@"\n"];
	[string im_appendString:IMLocalizedString(@"Status")];
	[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
	[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
	[string im_appendString:self.status_name];
	if (self.bus_status_info.status > 0) {
		[string im_appendString:@"\n"];
		[string im_appendString:IMLocalizedString(@"Bus Status")];
		[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
		[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
		[string im_appendString:self.bus_status_info.statusName];
	}
	if (self.product.schedule_id) {
		[string im_appendString:@"\n"];
		[string im_appendString:IMLocalizedString(@"Bus ID")];
		[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
		[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
		[string im_appendString:self.product.schedule_id];
	} else if (self.product.tour_code) {
		[string im_appendString:@"\n"];
		[string im_appendString:IMLocalizedString(@"Tour Code")];
		[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
		[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
		[string im_appendString:self.product.tour_code];
	}
	if (self.product.is_bus) {
		[string im_appendString:@"\n"];
		[string im_appendString:IMLocalizedString(@"Operator")];
		[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
		[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
		[string im_appendString:self.product.vendor_obj.short_name];
	}
	[string im_appendString:@"\n"];
	[string im_appendString:@"\n"];
	[string im_appendString:IMLocalizedString(@"Order ID")];
	[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
	[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
	[string im_appendString:self.order.order_code];
	[string im_appendString:@"\n"];
	[string im_appendString:IMLocalizedString(@"Purchase Date")];
	[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
	[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
	[string im_appendString:self.order.localizedPurchaseDateString];
	if (self.order.entries.count > 1) {
		[string im_appendString:@"\n"];
		[string im_appendString:IMLocalizedString(@"Total Payment")];
		[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
		[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
		[string appendFormat:@"$%g", [[self.order.entries valueForKeyPath:@"@sum.sold_amount"] floatValue]];
	}
	if (self.order.customer_name) {
		[string im_appendString:@"\n"];
		[string im_appendString:IMLocalizedString(@"Purchaser")];
		[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
		[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
		[string im_appendString:self.order.customer_name];
	}
	if (self.order.customer_home_phone) {
		[string im_appendString:@"\n"];
		[string im_appendString:IMLocalizedString(@"Phone")];
		[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
		[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
		[string im_appendString:self.order.customer_home_phone];
	}
	if (self.order.customer_email) {
		[string im_appendString:@"\n"];
		[string im_appendString:IMLocalizedString(@"Email")];
		[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
		[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
		[string im_appendString:self.order.customer_email];
	}
	return [NSString stringWithString:string];
}

- (NSString *)shortDescription {
	NSInteger roomNum = self.rooms.count;
	if (roomNum > 0) {
		NSString *roomString = [NSString stringWithFormat:roomNum > 1 ? IMLocalizedString(@"%d rooms") : IMLocalizedString(@"%d room"), roomNum];
		NSInteger stockNum = self.serialStocks.count;
		NSString *stockString = stockString = [NSString stringWithFormat:stockNum > 1 ? IMLocalizedString(@"%d travelers") : IMLocalizedString(@"%d traveler"), stockNum];
		NSMutableString *string = [NSMutableString string];
		[string im_appendString:stockString];
		[string im_appendString:@" / "];
		[string im_appendString:roomString];
		return [NSString stringWithString:string];
	} else {
		NSInteger stockNum = self.stocks.count;
		NSString *stockString = stockString = [NSString stringWithFormat:stockNum > 1 ? IMLocalizedString(@"%d travelers") : IMLocalizedString(@"%d traveler"), stockNum];
		return stockString;
	}
}

- (NSString *)busRouteName {
	if (self.product.is_bus && self.firstDepartureStop && self.lastArrivalStop) {
		return [NSString stringWithFormat:@"%@ to %@", [Destination cityName:self.firstDepartureStop.station.destination.show_name], [Destination cityName:self.lastArrivalStop.station.destination.show_name]];
	}
	return self.product.busRouteName;
}

#pragma mark - Public

- (BOOL)hasOption:(NSString *)alias {
	NSArray *option_values = [self.serialStocks valueForKeyPath:[@"@distinctUnionOfObjects.desc." im_stringByAppendingString:alias]];
	if (option_values.count == 0) {
		NSArray *newoption_values = [self.serialStocks valueForKeyPath:[@"@distinctUnionOfObjects.desc." im_stringByAppendingString:[NSString stringWithFormat:@"description_%@",alias]]];
		return newoption_values.count > 0;
	} else {
		return option_values.count > 0;
	}
	
}

- (NSString *)getOptionText:(NSString *)alias {
	NSArray *option_values = [[self.serialStocks valueForKeyPath:[@"@distinctUnionOfObjects.desc." im_stringByAppendingString:alias]] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
	if (option_values.count > 1) {
		NSMutableArray *array = [NSMutableArray array];
		for (NSString *option_value in [option_values sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]) {
			NSArray *stocks = [self.serialStocks bk_select:^BOOL (SoldStock *obj) {
				return [obj.desc[alias] isEqualToString:option_value];
			}];
			NSMutableString *string = [NSMutableString string];
			[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
			[string im_appendString:IMLocalizedString(PUNCTUATION_PARENTHESES_LEFT)];
			[string im_appendString:[[stocks valueForKeyPath:@"sold_to_name"] componentsJoinedByString:[StringUtils join:IMLocalizedString(PUNCTUATION_COMMA), IMLocalizedString(WORD_DIVIDER_SPACE), nil]]];
			[string im_appendString:IMLocalizedString(PUNCTUATION_PARENTHESES_RIGHT)];
			[string insertString:option_value atIndex:0];
			[array addObject:string];
		}
		return [array componentsJoinedByString:@"\n"];
	} else if (option_values.count == 1) {
		NSString *option_value = option_values.firstObject;
		return option_value;
	}
	return nil;
}

- (NSAttributedString *)getOptionAttributedText:(NSString *)alias withFont:(UIFont *)font {
	NSArray *option_values = [[self.serialStocks valueForKeyPath:[@"@distinctUnionOfObjects.desc." im_stringByAppendingString:alias]] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
	if (option_values.count == 0) {
		 option_values = [[self.serialStocks valueForKeyPath:[@"@distinctUnionOfObjects.desc." im_stringByAppendingString:[NSString stringWithFormat:@"description_%@",alias]]] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
	}
	BOOL isHtmlAvailable = [alias isEqualToString:@"departure"] || [alias isEqualToString:@"arrival"];
	if (option_values.count > 1) {
		NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];
		for (NSString *option_value in option_values) {
			if (isHtmlAvailable ) {
				[attributedString appendAttributedString:[Utility attributedStringWithHtmlString:option_value fixAttributes:@{ NSFontAttributeName : font }]];
			} else {
				[attributedString appendAttributedString:[[NSAttributedString alloc] im_initWithString:option_value attributes:@{ NSFontAttributeName : font }]];
			}
			
			NSArray *stocks = [self.serialStocks bk_select:^BOOL (SoldStock *obj) {
				return [obj.desc[alias] isEqualToString:option_value];
			}];
			NSMutableString *string = [NSMutableString string];
			[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
			[string im_appendString:IMLocalizedString(PUNCTUATION_PARENTHESES_LEFT)];
			[string im_appendString:[[stocks valueForKeyPath:@"sold_to_name"] componentsJoinedByString:[StringUtils join:IMLocalizedString(PUNCTUATION_COMMA), IMLocalizedString(WORD_DIVIDER_SPACE), nil]]];
			[string im_appendString:IMLocalizedString(PUNCTUATION_PARENTHESES_RIGHT)];
			[attributedString appendAttributedString:[[NSAttributedString alloc] im_initWithString:string attributes:@{ NSForegroundColorAttributeName : [UIColor darkGrayColor], NSFontAttributeName : font }]];
			if (option_value != option_values.lastObject) {
				[attributedString appendAttributedString:[[NSAttributedString alloc] im_initWithString:@"\n"]];
			}
		}
		return [[NSAttributedString alloc] initWithAttributedString:attributedString];
	} else if (option_values.count == 1) {
		NSString *option_value = option_values.firstObject;
		if (isHtmlAvailable ) {
			return [Utility attributedStringWithHtmlString:option_value fixAttributes:@{ NSFontAttributeName : font }];
		} else {
			return [[NSAttributedString alloc] im_initWithString:option_value attributes:@{ NSFontAttributeName : font }];
		}
	}
	return nil;
}

- (NSString *)peopleDescriptionAtRoomNo:(NSInteger)roomNo {
	if (roomNo < 1 || roomNo > self.rooms.count) {
		return nil;
	}
	SalesEntryRoom *room = self.rooms[roomNo - 1];
	NSMutableArray *array = [NSMutableArray array];
	for (NSString *type in [RoomBasedPrice defaultPossibleTypes]) {
		NSArray *stocks = [SoldStock filteredStocks:room.stocks byBasedType:type];
		if (stocks.count > 0) {
			NSMutableString *string = [NSMutableString string];
			[string im_appendString:IMLocalizedString(type)];
			[string im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
			[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
			[string appendFormat:@"%d", stocks.count];
			NSMutableArray *array1 = [NSMutableArray array];
			[stocks enumerateObjectsUsingBlock:^(SoldStock *obj, NSUInteger idx, BOOL *stop) {
				if (obj.people_age >= 0) {
					NSMutableString *string1 = [NSMutableString string];
					[string1 im_appendString:IMLocalizedString(@"Age")];
					[string1 appendFormat:@"%d", idx + 1];
					[string1 im_appendString:IMLocalizedString(PUNCTUATION_COLON)];
					[string1 im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
					[string1 appendFormat:@"%d", obj.people_age];
					[array1 addObject:string1];
				}
			}];
			if (array1.count > 0) {
				[string im_appendString:IMLocalizedString(WORD_DIVIDER_SPACE)];
				[string im_appendString:IMLocalizedString(PUNCTUATION_PARENTHESES_LEFT)];
				[string im_appendString:[array1 componentsJoinedByString:[StringUtils join:IMLocalizedString(PUNCTUATION_COMMA), IMLocalizedString(WORD_DIVIDER_SPACE), nil]]];
				[string im_appendString:IMLocalizedString(PUNCTUATION_PARENTHESES_RIGHT)];
			}
			[array addObject:string];
		}
	}
	return [array componentsJoinedByString:[StringUtils join:IMLocalizedString(PUNCTUATION_COMMA), IMLocalizedString(WORD_DIVIDER_SPACE), nil]];
}

#pragma mark - Private

- (BOOL)isMultipleOption:(NSString *)alias {
	NSArray *option_values = [self.serialStocks valueForKeyPath:[@"@distinctUnionOfObjects.desc." im_stringByAppendingString:alias]];
	return option_values.count > 1;
}

@end
