//
//  SelectLocationViewController.m
//  Project
//
//  Created by 包光清 on 2018/6/11.
//

#import "SelectLocationViewController.h"
#import "Lang.h"
#import "SDK.h"
#import "AppTracker.h"
#import "CocoaUtils.h"
#import "DrawUtils.h"
#import "BasePopView.h"
#import "NavigationItemSheet.h"
#import "UIConstants.h"
#import "UIToolkit.h"
#import "SMMapView.h"
#import "SMModernCalloutView.h"
#import <BlocksKit/BlocksKit+UIKit.h>
#import <BlocksKit/A2DynamicDelegate.h>
#import <BlocksKit/NSObject+A2DynamicDelegate.h>
#import <libextobjc/EXTScope.h>
#import <PureLayout/PureLayout.h>
#import "Utility.h"
#import "Vars.h"

@interface SelectLocationViewController () <UITableViewDataSource, UITableViewDelegate> {
	BOOL _restorationDidLayout;
}

@property (nonatomic, strong) BasePopView *departAndArrivalView;
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSLayoutConstraint *topPopViewConstraint;

@property (nonatomic, strong) NSArray *cellDataArrays;

@property (nonatomic, strong) NSMutableArray<NSString *> *departureSectionTitles;
@property (nonatomic, strong) NSMutableArray<NSArray<MapViewAnnotation *> *> *departureSortedArrays;
@property (nonatomic, assign) NSInteger departureSectionIndex;
@property (nonatomic, strong) MapViewAnnotation *departureSelectedAnnotation;
@property (nonatomic, strong) NSMutableArray<NSString *> *arrivalSectionTitles;
@property (nonatomic, strong) NSMutableArray<NSArray<MapViewAnnotation *> *> *arrivalSortedArrays;
@property (nonatomic, assign) NSInteger arrivalSectionIndex;
@property (nonatomic, strong) MapViewAnnotation *arrivalSelectedAnnotation;

@property (nonatomic, copy) void (^didCancelBlock) (void);
@property (nonatomic, copy) void (^didDoneBlock) (MapViewAnnotation *annotation);
@property (nonatomic, copy) void (^didDoneDepartureAndArrivalBlock) (MapViewAnnotation *departureAnnotation, MapViewAnnotation *arrivalAnnotation);

@property (nonatomic, strong, readonly) NSArray<NSString *> *currentSectionTitles;
@property (nonatomic, strong, readonly) NSArray<NSArray<MapViewAnnotation *> *> *currentSortedArrays;
@property (nonatomic, assign, readwrite) NSInteger currentSectionIndex;
@property (nonatomic, strong, readwrite) MapViewAnnotation *currentSelectedAnnotation;
@property (nonatomic, strong, readonly) NSArray<MapViewAnnotation *> *currentShownAnnotations;

@end

@implementation SelectLocationViewController

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
	return [super initWithNibName:NSStringFromClass(self.superclass) bundle:nil];
}

- (instancetype)init {
	if (self = [super init]) {
		self.hidesBottomBarWhenPushed = YES;
		[[Vars appDelegate] applyDefaultConfigurationForViewController:self];
		// Custom initialization
		self.isArrival = NO;
		self.departureSectionIndex = NSNotFound;
		self.departureSectionTitles = [NSMutableArray array];
		self.departureSortedArrays = [NSMutableArray array];
		self.arrivalSectionIndex = NSNotFound;
		self.arrivalSectionTitles = [NSMutableArray array];
		self.arrivalSortedArrays = [NSMutableArray array];
	}
	return self;
}

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (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.didDoneDepartureAndArrivalBlock) {
		self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] im_initWithBarButtonSystemItem:UIBarButtonSystemItemDone handler:^(UIBarButtonItem *barButtonItem) {
			@strongify(self)
			self.didDoneDepartureAndArrivalBlock(self.departureSelectedAnnotation, self.arrivalSelectedAnnotation);
		}];
	} else if (self.didDoneBlock) {
		self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] im_initWithBarButtonSystemItem:UIBarButtonSystemItemDone handler:^(UIBarButtonItem *barButtonItem) {
			@strongify(self)
			self.didDoneBlock(self.departureSelectedAnnotation);
		}];
    }
	
	if (self.departureSortedArrays.count > 0 && self.departureSectionIndex == NSNotFound) {
		self.departureSectionIndex = 0;
	}
	if (self.arrivalSortedArrays.count > 0 && self.arrivalSectionIndex == NSNotFound) {
		self.arrivalSectionIndex = 0;
	}

	[self buildCellDataSource];
	[self reloadMapView];
}

- (void)viewWillLayoutSubviews {
	[super viewWillLayoutSubviews];
}

- (void)viewDidLayoutSubviews {
	[super viewDidLayoutSubviews];
	
	if (!_restorationDidLayout) {
		[self setDepartAndArrivalView];
		[self toggleMapView];
		_restorationDidLayout = YES;
	}
}

#pragma mark - Protected

- (void)didSelectAnnotation:(MapViewAnnotation *)annotation {
	[self selectAnnotation:annotation isArrival:self.isArrival];
	[self.tableView reloadData];
	[self toggleTableView];
}

#pragma mark - Public

- (NSArray<MapViewAnnotation *> *)getAnnotations {
	return [self getAnnotationsIsArrival:NO];
}

- (NSArray<MapViewAnnotation *> *)getAnnotationsIsArrival:(BOOL)isArrival {
	if (isArrival) {
		return [self.arrivalSortedArrays valueForKeyPath:@"@unionOfArrays.self"];
	} else {
		return [self.departureSortedArrays valueForKeyPath:@"@unionOfArrays.self"];
	}
}

- (void)addAnnotations:(NSArray *)annotations title:(NSString *)title {
	[self addAnnotations:annotations title:title isArrival:NO];
}

- (void)addAnnotations:(NSArray *)annotations title:(NSString *)title isArrival:(BOOL)isArrival {
	if (!annotations || !title) {
		return;
	}
	if (isArrival) {
		[self.arrivalSectionTitles addObject:title];
		[self.arrivalSortedArrays addObject:annotations];
	} else {
		[self.departureSectionTitles addObject:title];
		[self.departureSortedArrays addObject:annotations];
	}
}

- (void)selectAnnotation:(MapViewAnnotation *)annotation {
	[self selectAnnotation:annotation isArrival:NO];
}

- (void)selectAnnotation:(MapViewAnnotation *)annotation isArrival:(BOOL)isArrival {
	if (isArrival) {
		[self.arrivalSortedArrays enumerateObjectsUsingBlock:^(NSArray *annotations, NSUInteger idx, BOOL *stop) {
			if ([annotations containsObject:annotation]) {
				self.arrivalSectionIndex = idx;
				self.arrivalSelectedAnnotation = annotation;
				*stop = YES;
				return;
			}
		}];
	} else {
		[self.departureSortedArrays enumerateObjectsUsingBlock:^(NSArray *annotations, NSUInteger idx, BOOL *stop) {
			if ([annotations containsObject:annotation]) {
				self.departureSectionIndex = idx;
				self.departureSelectedAnnotation = annotation;
				*stop = YES;
				return;
			}
		}];
	}
}

- (void)selectTitle:(NSString *)title {
	[self selectTitle:title isArrival:NO];
}

- (void)selectTitle:(NSString *)title isArrival:(BOOL)isArrival {
	if (isArrival) {
		[self.arrivalSectionTitles enumerateObjectsUsingBlock:^(NSString *obj, NSUInteger idx, BOOL *stop) {
			if ([obj isEqualToString:title]) {
				self.arrivalSectionIndex = idx;
				*stop = YES;
				return;
			}
		}];
	} else {
		[self.departureSectionTitles enumerateObjectsUsingBlock:^(NSString *obj, NSUInteger idx, BOOL *stop) {
			if ([obj isEqualToString:title]) {
				self.departureSectionIndex = idx;
				*stop = YES;
				return;
			}
		}];
	}
}

#pragma mark - Property

- (NSArray<NSString *> *)currentSectionTitles {
	return self.isArrival ? self.arrivalSectionTitles : self.departureSectionTitles;
}

- (NSArray<NSArray<MapViewAnnotation *> *> *)currentSortedArrays {
	return self.isArrival ? self.arrivalSortedArrays : self.departureSortedArrays;
}

- (NSArray<MapViewAnnotation *> *)currentShownAnnotations {
	return self.currentSectionIndex != NSNotFound ? self.currentSortedArrays[self.currentSectionIndex] : nil;
}

- (void)setCurrentSectionIndex:(NSInteger)currentSectionIndex {
	if (self.isArrival) {
		self.arrivalSectionIndex = currentSectionIndex;
	} else {
		self.departureSectionIndex = currentSectionIndex;
	}
}

- (NSInteger)currentSectionIndex {
	return self.isArrival ? self.arrivalSectionIndex : self.departureSectionIndex;
}

- (void)setCurrentSelectedAnnotation:(MapViewAnnotation *)currentSelectedAnnotation {
	if (self.isArrival) {
		self.arrivalSelectedAnnotation = currentSelectedAnnotation;
	} else {
		self.departureSelectedAnnotation = currentSelectedAnnotation;
	}
}

- (MapViewAnnotation *)currentSelectedAnnotation {
	return self.isArrival ? self.arrivalSelectedAnnotation : self.departureSelectedAnnotation;
}

#pragma mark - Action

- (void)changeAnnotation:(MapViewAnnotation *)annotation onTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath {
    if (![self.currentSelectedAnnotation isEqual:annotation]) {
		[self selectAnnotation:annotation isArrival:self.isArrival];
		[tableView reloadData];
		[self toggleMapView];
    }
}

- (void)segmentAction:(UISegmentedControl *)seg {
	[self clearMapView];
	NSInteger index = seg.selectedSegmentIndex;
	if (index == 0) {
		self.isArrival = NO;
	} else if (index == 1) {
		self.isArrival = YES;
	}
	[self reloadTableView];
	[self reloadMapView];
	[self toggleTableView];
	[self toggleMapView];
}

#pragma mark - Private

- (void)setDepartAndArrivalView {
	CGFloat bottomMargin = 5;
	if (@available(iOS 11, *)) {
		if ([CocoaUtils isIPhoneX]) {
			bottomMargin = MAX(bottomMargin, self.view.safeAreaInsets.bottom + 30);
		}
	}
	if (YES) {
		self.departAndArrivalView = [[BasePopView alloc] initWithFrame:self.view.frame];
		self.departAndArrivalView.backgroundColor = [UIColor whiteColor];
		self.departAndArrivalView.minimumHeight = 10 + bottomMargin;
		self.departAndArrivalView.baselineHeight = ceil(CGRectGetHeight(self.view.frame) /  3);
		self.departAndArrivalView.maximumHeight = CGRectGetHeight(self.view.frame) - 15;
		@weakify(self)
		[self.departAndArrivalView setChangePopViewFrame:^(CGFloat scrollHeight) {
			@strongify(self)
			self.topPopViewConstraint.constant = scrollHeight;
			[UIView animateWithDuration:0 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
				[self.view layoutIfNeeded];
			} completion:nil];
		}];
		[self.departAndArrivalView setDidChangePopViewFrame:^(CGFloat scrollHeight) {
			@strongify(self)
			self.topPopViewConstraint.constant = scrollHeight;
			if (self.departAndArrivalView.popViewState == PopViewSizeTypeAll) {
				self.tableView.scrollEnabled = YES;
			} else {
				self.tableView.scrollEnabled = NO;
			}
			if (self.departAndArrivalView.popViewState == PopViewSizeTypeHalf) {
				self.tableView.contentInset = UIEdgeInsetsMake(0, 0, self.departAndArrivalView.maximumHeight - self.departAndArrivalView.baselineHeight, 0);
			} else {
				self.tableView.contentInset = UIEdgeInsetsZero;
			}
			[UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.7 initialSpringVelocity:0.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
				[self.view layoutIfNeeded];
			} completion:nil];
		}];
		[DrawUtils addRoundedBorderToRect:self.departAndArrivalView byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight cornerRadius:10];
		[self.view addSubview:self.departAndArrivalView];
		[self.departAndArrivalView autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:0];
		[self.departAndArrivalView autoAlignAxisToSuperviewAxis:ALAxisVertical];
		self.topPopViewConstraint = [self.mapView autoPinEdge:ALEdgeBottom toEdge:ALEdgeTop ofView:self.departAndArrivalView withOffset:self.departAndArrivalView.baselineHeight];
		[self.departAndArrivalView autoSetDimension:ALDimensionHeight toSize:self.departAndArrivalView.maximumHeight];
	}
	UIView *prevView = nil;
	if (YES) {
		UIButton *grayLineButton = [[UIButton alloc] init];
		grayLineButton.backgroundColor = [UIColor lightGrayColor];
		[Utility addRoundedBorderToButton:grayLineButton];
		[self.departAndArrivalView addSubview:grayLineButton];
		[grayLineButton autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:5];
		[grayLineButton autoAlignAxisToSuperviewAxis:ALAxisVertical];
		[grayLineButton autoSetDimension:ALDimensionWidth toSize:50];
		[grayLineButton autoSetDimension:ALDimensionHeight toSize:5];
		prevView = grayLineButton;
	}
	if (self.arrivalSectionTitles.count > 0 && self.arrivalSortedArrays.count > 0) {
		NSArray *segarray = [NSArray arrayWithObjects:IMLocalizedString(@"Departure"),IMLocalizedString(@"Arrival"),nil];
		UISegmentedControl *segmentC = [[UISegmentedControl alloc]initWithItems:segarray];
		segmentC.selectedSegmentIndex = self.isArrival ? 1 : 0;
		[segmentC addTarget:self action:@selector(segmentAction:) forControlEvents:UIControlEventValueChanged];
		[self.departAndArrivalView addSubview:segmentC];
		[segmentC autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:prevView withOffset:5];
		[segmentC autoAlignAxisToSuperviewAxis:ALAxisVertical];
		[segmentC autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:[UIConstants defaultTableViewCellLayoutInsets].left];
		[segmentC autoSetDimension:ALDimensionHeight toSize:[UIConstants defaultSegmentedControlHeight]];
		prevView = segmentC;
	}
	if (YES) {
		
		self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
		self.tableView.delegate = self;
		self.tableView.dataSource = self;
		[self.departAndArrivalView addSubview:self.tableView];
		[self.tableView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:prevView withOffset:10];
		[self.tableView autoAlignAxisToSuperviewAxis:ALAxisVertical];
		[self.tableView autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:0];
		[self.tableView autoPinEdgeToSuperviewEdge:ALEdgeBottom];
	}
	self.departAndArrivalView.popViewState = PopViewSizeTypeHalf;
	self.tableView.scrollEnabled = NO;
	self.tableView.contentInset = UIEdgeInsetsMake(0, 0, self.departAndArrivalView.maximumHeight - self.departAndArrivalView.baselineHeight, 0);
}

- (void)buildCellDataSource {
    NSMutableArray *arrays = [NSMutableArray array];
    @weakify(self)
        for (NSArray<NSArray<MapViewAnnotation *> *> *annotationList in self.currentSortedArrays) {
            NSMutableArray *array = [NSMutableArray array];
            for (MapViewAnnotation *annotation in annotationList) {
				TableViewCellData *data = [[TableViewCellData alloc] init];
				data.attributedText = [Utility attributedStringWithHtmlString:annotation.label fixAttributes:@{ NSFontAttributeName : [UIConstants defaultTableViewCellTextLabelFont:UITableViewCellStyleDefault] }];
				data.allowsTextLineWrapping = YES;
                [data setAccessoryTypeBlock:^UITableViewCellAccessoryType {
                    @strongify(self)
                    if ([self.currentSelectedAnnotation isEqual:annotation]) {
                        return UITableViewCellAccessoryCheckmark;
                    }
                    return UITableViewCellAccessoryNone;
                }];
                [data setVaryingHeightIdentifierBlock:^NSString *(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data){
                    @strongify(self)
                    return [NSString stringWithFormat:@"%d", [self.currentSelectedAnnotation isEqual:annotation]];
                }];
                [data setDidSelectBlock:^(UITableView *tableView, NSIndexPath *indexPath, TableViewCellData *data) {
                    @strongify(self)
                    [self changeAnnotation: annotation onTableView:tableView atIndexPath: indexPath];
                }];
                [array addObject:data];
            }
            [arrays addObject:[NSArray arrayWithArray:array]];
        }
    self.cellDataArrays = [NSArray arrayWithArray:arrays];
}

- (void)scrollToSelectionOnTableView:(UITableView *)tableView {
	if (self.currentSectionIndex != NSNotFound) {
		if (self.currentSelectedAnnotation) {
			NSIndexPath *indexPath = [CocoaUtils indexPathOfObjectIdenticalTo:self.currentSelectedAnnotation fromArray:self.currentShownAnnotations inSection:self.currentSectionIndex];
			if (indexPath) {
				[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
			}
		} else {
			NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:self.currentSectionIndex];
			if (indexPath) {
				[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
			}
		}
	}
}

- (void)reloadTableView {
	[self buildCellDataSource];
	[self.tableView reloadData];
}

- (void)toggleTableView {
	[self scrollToSelectionOnTableView:self.tableView];
}

- (void)clearMapView {
	[self.mapView removeAnnotations:[self getAnnotationsIsArrival:self.isArrival]];
}

- (void)reloadMapView {
	[self.mapView addAnnotations:[self getAnnotationsIsArrival:self.isArrival]];
}

- (void)toggleMapView {
	[self.mapView showAnnotations:self.currentShownAnnotations animated:NO];
	[self.mapView setVisibleMapRect:self.mapView.visibleMapRect edgePadding:UIEdgeInsetsMake(0, 0, self.departAndArrivalView.baselineHeight, 0) animated:NO];
	if ([self.currentShownAnnotations containsObject:self.currentSelectedAnnotation]) {
		[self.mapView selectAnnotation:self.currentSelectedAnnotation animated:NO];
	}
}

#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 {
	return self.currentSectionTitles[section];
}

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

- (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
