//
// CalendarBuilder.m
// Project
//
// Created by 杨殷杭 on 16/12/27.
//
//

#import "CalendarManager.h"
#import "CocoaUtils.h"
#import <BlocksKit/BlocksKit.h>

@interface RangePickerCell : FSCalendarCell

// The start/end of the range
@property (weak, nonatomic) CALayer *selectionLayer;

// The middle of the range
@property (weak, nonatomic) CALayer *middleLayer;

@end

@implementation RangePickerCell

- (instancetype)initWithFrame:(CGRect)frame
{
	self = [super initWithFrame:frame];
	if (self) {
		
		CALayer *selectionLayer = [[CALayer alloc] init];
		selectionLayer.backgroundColor = [UIColor orangeColor].CGColor;
		selectionLayer.actions = @{@"hidden":[NSNull null]}; // Remove hiding animation
		[self.contentView.layer insertSublayer:selectionLayer below:self.titleLabel.layer];
		self.selectionLayer = selectionLayer;
		
		CALayer *middleLayer = [[CALayer alloc] init];
		middleLayer.backgroundColor = [[UIColor orangeColor] colorWithAlphaComponent:0.3].CGColor;
		middleLayer.actions = @{@"hidden":[NSNull null]}; // Remove hiding animation
		[self.contentView.layer insertSublayer:middleLayer below:self.titleLabel.layer];
		self.middleLayer = middleLayer;
		
		// Hide the default selection layer
		self.shapeLayer.hidden = YES;
		
	}
	return self;
}

- (void)layoutSubviews
{
	[super layoutSubviews];
	self.titleLabel.frame = self.contentView.bounds;
}

- (void)layoutSublayersOfLayer:(CALayer *)layer
{
	[super layoutSublayersOfLayer:layer];
	self.selectionLayer.frame = self.contentView.bounds;
	self.middleLayer.frame = self.contentView.bounds;
}

@end

@interface FSCalendar ()
@property (strong, nonatomic) NSCalendar *gregorian;
@end

@interface CalendarManager ()
@property (nonatomic, assign) BOOL allowsRangeSelection;
@property (nonatomic, strong) NSDate *startDate;
@property (nonatomic, strong) NSDate *endDate;
@property (nonatomic, copy) void (^didSelectDateBlock) (NSDate *date);
@end

@implementation CalendarManager

#pragma mark - <FSCalendarDataSource>

- (NSDate *)minimumDateForCalendar:(FSCalendar *)calendar {
	return self.minimumDate;
}

- (NSDate *)maximumDateForCalendar:(FSCalendar *)calendar {
	return self.maximumDate;
}

- (__kindof FSCalendarCell *)calendar:(FSCalendar *)calendar cellForDate:(NSDate *)date atMonthPosition:(FSCalendarMonthPosition)position {
	return [calendar dequeueReusableCellWithIdentifier:self.allowsRangeSelection ? NSStringFromClass([RangePickerCell class]) : FSCalendarDefaultCellReuseIdentifier forDate:date atMonthPosition:position];
}

#pragma mark - <FSCalendarDelegate>

- (BOOL)calendar:(FSCalendar *)calendar shouldSelectDate:(NSDate *)date atMonthPosition:(FSCalendarMonthPosition)monthPosition {
	return !self.enabledDates || [self.enabledDates containsObject:date];
}

- (BOOL)calendar:(FSCalendar *)calendar shouldDeselectDate:(NSDate *)date atMonthPosition:(FSCalendarMonthPosition)monthPosition {
	if (self.allowsRangeSelection) {
		return NO;
	} else if (calendar.allowsMultipleSelection) {
		return YES;
	}
	return NO;
}

- (void)calendar:(FSCalendar *)calendar willDisplayCell:(FSCalendarCell *)cell forDate:(NSDate *)date atMonthPosition:(FSCalendarMonthPosition)monthPosition {
	if (self.allowsRangeSelection) {
		[self configureCell:cell forDate:date atMonthPosition:monthPosition onCalendar:calendar];
	}
}

- (void)calendar:(FSCalendar *)calendar didSelectDate:(NSDate *)date atMonthPosition:(FSCalendarMonthPosition)monthPosition {
	if (self.allowsRangeSelection) {
		if (calendar.swipeToChooseGesture.state == UIGestureRecognizerStateChanged) {
			// If the selection is caused by swipe gestures
			if (!self.startDate) {
				self.startDate = date;
			} else {
				if (self.endDate) {
					[calendar deselectDate:self.endDate];
				}
				self.endDate = date;
			}
		} else {
			if (self.endDate) {
				[calendar deselectDate:self.startDate];
				[calendar deselectDate:self.endDate];
				self.startDate = date;
				self.endDate = nil;
			} else if (!self.startDate) {
				self.startDate = date;
			} else {
				self.endDate = date;
			}
		}
		[self configureVisibleCellsOnCalendar:calendar];
	} else {
		if (self.didSelectDateBlock) {
			self.didSelectDateBlock(date);
		}
	}
}

- (void)calendar:(FSCalendar *)calendar didDeselectDate:(NSDate *)date atMonthPosition:(FSCalendarMonthPosition)monthPosition {
	if (self.allowsRangeSelection) {
		[self configureVisibleCellsOnCalendar:calendar];
	}
}

#pragma mark - <FSCalendarDelegateAppearance>

- (UIColor *)calendar:(FSCalendar *)calendar appearance:(FSCalendarAppearance *)appearance titleDefaultColorForDate:(NSDate *)date {
	return !self.enabledDates || [self.enabledDates containsObject:date] ? nil : [UIColor lightGrayColor];
}

#pragma mark - Public

+ (void)calendar:(FSCalendar *)calendar setCurrentPage:(NSDate *)currentPage {
	if ([self calendar:calendar containsDate:currentPage]) {
		[calendar setCurrentPage:currentPage];
	}
}

+ (void)calendar:(FSCalendar *)calendar selectDate:(NSDate *)date {
	if ([self calendar:calendar containsDate:date]) {
		[calendar selectDate:date];
	}
}

+ (void)calendar:(FSCalendar *)calendar selectDates:(NSArray<NSDate *> *)dates {
	[[dates bk_select:^BOOL (id obj) {
		return [self calendar:calendar containsDate:obj];
	}] enumerateObjectsUsingBlock:^(NSDate *date, NSUInteger idx, BOOL *stop) {
		[calendar selectDate:date scrollToDate:idx == 0 ? YES : NO];
	}];
}

- (void)configureRangeSelectionCalendar:(FSCalendar *)calendar {
	self.allowsRangeSelection = YES;
	calendar.allowsMultipleSelection = YES;
	calendar.swipeToChooseGesture.enabled = YES;
	calendar.today = nil;
	[calendar registerClass:[RangePickerCell class] forCellReuseIdentifier:NSStringFromClass([RangePickerCell class])];
}

- (void)calendar:(FSCalendar *)calendar selectRangeFromStartDate:(NSDate *)startDate toEndDate:(NSDate *)endDate {
	if (startDate && endDate) {
		if ([CalendarManager calendar:calendar containsDate:startDate]) {
			[calendar selectDate:startDate scrollToDate:NO];
			self.startDate = startDate;
		}
		if ([CalendarManager calendar:calendar containsDate:endDate]) {
			[calendar selectDate:endDate];
			self.endDate = endDate;
		}
	}
	if (self.startDate && self.endDate) {
		[self configureVisibleCellsOnCalendar:calendar];
	}
}

#pragma mark - Private

+ (BOOL)calendar:(FSCalendar *)calendar containsDate:(NSDate *)date {
	if (calendar.minimumDate && [date compare:calendar.minimumDate] == NSOrderedAscending) {
		return NO;
	}
	if (calendar.maximumDate && [date compare:calendar.maximumDate] == NSOrderedDescending) {
		return NO;
	}
	if ([calendar.delegate respondsToSelector:@selector(calendar:shouldSelectDate:atMonthPosition:)]) {
		return [calendar.delegate calendar:calendar shouldSelectDate:date atMonthPosition:FSCalendarMonthPositionNotFound];
	}
	return YES;
}

- (void)configureVisibleCellsOnCalendar:(FSCalendar *)calendar {
	[calendar.visibleCells enumerateObjectsUsingBlock:^(__kindof FSCalendarCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
		NSDate *date = [calendar dateForCell:obj];
		FSCalendarMonthPosition position = [calendar monthPositionForCell:obj];
		[self configureCell:obj forDate:date atMonthPosition:position onCalendar:calendar];
	}];
}

- (void)configureCell:(RangePickerCell *)cell forDate:(NSDate *)date atMonthPosition:(FSCalendarMonthPosition)position onCalendar:(FSCalendar *)calendar {
	if (position != FSCalendarMonthPositionCurrent) {
		cell.middleLayer.hidden = YES;
		cell.selectionLayer.hidden = YES;
		return;
	}
	if (self.startDate && self.endDate) {
		// The date is in the middle of the range
		BOOL isMiddle = [date compare:self.startDate] != [date compare:self.endDate];
		cell.middleLayer.hidden = !isMiddle;
	} else {
		cell.middleLayer.hidden = YES;
	}
	BOOL isSelected = NO;
	isSelected |= self.startDate && [calendar.gregorian isDate:date inSameDayAsDate:self.startDate];
	isSelected |= self.endDate && [calendar.gregorian isDate:date inSameDayAsDate:self.endDate];
	cell.selectionLayer.hidden = !isSelected;
}

@end
