//
// TrackBusStatusMapViewController.m
// Project
//
// Created by Ziv on 2017/5/17.
//
//

#import "BusStatusMapViewController.h"
#import "Lang.h"
#import "SDK.h"
#import "CocoaUtils.h"
#import "DrawUtils.h"
#import "ImageUtils.h"
#import "PointAnnotation.h"
#import "UIConstants.h"
#import "UIToolkit.h"
#import <BlocksKit/BlocksKit.h>
#import <BlocksKit/BlocksKit+UIKit.h>
#import <libextobjc/EXTScope.h>
#import <PureLayout/PureLayout.h>
#import "Utility.h"
#import "CustomIcons.h"
#import "BusStatusApi.h"
#import "BusStatusDetailStopCell.h"
#import "BusStatusDetailStopView.h"
#import "UIViewController+Privilege.h"
#ifndef TARGET_OF_Chinatown_Bus
 #import "SchedulePassengerListViewController.h"
#endif
#import "Vars.h"

@interface BusStatusMapViewController () <MKMapViewDelegate>
@property (nonatomic, strong) NSMutableArray<PointAnnotation *> *mutableAnnotations;
@property (nonatomic, strong, readonly) NSArray<ScheduleStop *> *scheduleStops;
@end

@implementation BusStatusMapViewController

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

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

- (void)viewDidLoad {
	[super viewDidLoad];

	self.mutableAnnotations = [NSMutableArray array];

	self.mapView.delegate = self;
	self.mapView.showsCompass = NO;

//	if (self.allowsEditing) {
//#ifndef TARGET_OF_Chinatown_Bus
//		if ([Vars appDelegate].loginUser.is_vendor) {
//			if (self.busStatusDetailResponse.stopIndex >= 0 && self.busStatusDetailResponse.stopIndex < self.busStatusDetailResponse.resultList.count -1) {
//				BusStatusDetailBean *bean = self.busStatusDetailResponse.resultList[self.busStatusDetailResponse.stopIndex];
//				BusStatusDetailBean *nextBean = self.busStatusDetailResponse.resultList[self.busStatusDetailResponse.stopIndex + 1];
//				if (YES) {
//					NSMutableSet<DriverBean *> *driverSet = [NSMutableSet setWithArray:bean.assignedDrivers];
//					NSSet<DriverBean *> *nextDriverSet = [NSSet setWithArray:nextBean.assignedDrivers];
//					[driverSet intersectSet:nextDriverSet];
//
//					if (driverSet.count > 0) {
//						UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NSStringFromClass([UITableViewCell class])];
//						cell.backgroundColor = [UIColor whiteColor];
//						[Utility addRoundedBorderToButton:cell];
//						[DrawUtils addShadowToRect:cell];
//						[self.mapView addSubview:cell];
//						[cell autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:10];
//						[cell autoAlignAxisToSuperviewAxis:ALAxisVertical];
//						[cell autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:10];
//						[cell autoSetDimension:ALDimensionHeight toSize:[UIConstants defaultTableViewRowHeight]];
//
//						cell.imageView.image = [DrawUtils tableViewCellImageWithFAKIcon:[CustomIcons driverIconWithSize:24] fillColor:[UIColor lightGrayColor]];
//						cell.textLabel.text = [StringUtils isEmpty:driverSet.anyObject.name] ? @"N/A" : driverSet.anyObject.name;
//						BOOL isValidPhoneNumber = ![StringUtils isEmpty:driverSet.anyObject.phone] && [Utility isValidPhoneNumber:driverSet.anyObject.phone];
//						if (isValidPhoneNumber) {
//							UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
//							[button setImage:[DrawUtils imageWithFAKIcon:[FAKFontAwesome phoneIconWithSize:24] fillColor:[Vars defaultTintColor]] forState:UIControlStateNormal];
//							[button sizeToFit];
//							[button bk_addEventHandler:^(id sender) {
//								[Utility callPhoneNumber:driverSet.anyObject.phone];
//							} forControlEvents:UIControlEventTouchUpInside];
//							cell.accessoryView = button;
//						}
//					}
//				}
//				if (YES) {
//					UIView  *contanierView = [[UIView alloc] init];
//					contanierView.backgroundColor = [UIColor whiteColor];
//					[Utility addRoundedBorderToButton:contanierView];
//					[DrawUtils addShadowToRect:contanierView];
//					[self.mapView addSubview:contanierView];
//					[contanierView autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:10];
//					[contanierView autoAlignAxisToSuperviewAxis:ALAxisVertical];
//                    if ([CocoaUtils isIPhoneX]) {
//                        if (@available(iOS 11.0, *)) {
//                            [contanierView.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor].active = YES;
//                        }
//                    }else{
//                        [contanierView autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:10];
//                    }
//					BusStatusDetailStopView *view = [[BusStatusDetailStopView alloc] init];
//					view.backgroundColor = nextBean.isCancelled ? [UIColor lightGrayColor] : [UIColor whiteColor];
//					if (YES) {
//						UIFont *font1 = [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote];
//						UIFont *font2 = [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1];
//						NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];
//						[attributedString appendAttributedString:[DrawUtils attributedStringWithFAKIcon:[FAKFontAwesome arrowRightIconWithSize:font1.pointSize] fillColor:[UIColor lightGrayColor]]];
//						[attributedString appendAttributedString:[[NSAttributedString alloc] im_initWithString:@" "]];
//						[attributedString appendAttributedString:[[NSAttributedString alloc] im_initWithString:nextBean.scheduleStop.busstation.destination.show_name attributes:@{NSFontAttributeName : font1}]];
//						[attributedString appendAttributedString:[[NSAttributedString alloc] im_initWithString:@"\n"]];
//						[attributedString appendAttributedString:[[NSAttributedString alloc] im_initWithString:nextBean.scheduleStop.busstation.name attributes:@{NSFontAttributeName : font2}]];
//						view.stopNameLabel.attributedText = attributedString;
//					}
//					view.scheduledTimeLabel.attributedText = nextBean.attributedScheduledTimeText;
//					view.statusTimeLabel.attributedText = nextBean.attributedStatusTimeText;
//					view.showsToolbar = YES;
//                    view.showBottomToolbar = YES;
//                    if (bean.combinationArrCross || bean.combinationDepCross) {
//                        view.showBottomToolbar = NO;
//                        view.showsToolbar = NO;
//                    } else {
//                        if (!bean.scheduleStop.isPickUp) {
//                            view.showBottomToolbar = NO;
//                        }
//                        if (self.schedule.route.isCombinationRoute) {
//                           view.showBottomToolbar = NO;
//                        }
//                    }
//					view.driverInfoButton.hidden = YES;
//					view.isPickUp = nextBean.scheduleStop.isPickUp;
//					view.isDropOff = nextBean.scheduleStop.isDropOff;
//                    CGSize size = [view systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
//                    [contanierView autoSetDimension:ALDimensionHeight toSize:size.height];
//					if (nextBean.scheduleStop.isPickUp) {
//						[view.pickUpButton setTitle:[NSString stringWithFormat:@"%d", nextBean.scheduleStop.pickUpPassengerNum] forState:UIControlStateNormal];
//						[view.checkInButton setTitle:[NSString stringWithFormat:@"%d", nextBean.scheduleStop.checkInPassengerNum] forState:UIControlStateNormal];
//						[view.uncheckedButton setTitle:[NSString stringWithFormat:@"%d", nextBean.scheduleStop.uncheckedPassengerNum] forState:UIControlStateNormal];
//					} else {
//						[view.pickUpButton setTitle:@"N/A" forState:UIControlStateNormal];
//						[view.checkInButton setTitle:@"N/A" forState:UIControlStateNormal];
//						[view.uncheckedButton setTitle:@"N/A" forState:UIControlStateNormal];
//					}
//					if (nextBean.scheduleStop.isDropOff) {
//						[view.dropOffButton setTitle:[NSString stringWithFormat:@"%d", nextBean.scheduleStop.dropOffPassengerNum] forState:UIControlStateNormal];
//					} else {
//						[view.dropOffButton setTitle:@"N/A" forState:UIControlStateNormal];
//					}
//					@weakify(self)
//					if (nextBean.scheduleStop.isPickUp && nextBean.scheduleStop.pickUpPassengerNum > 0) {
//						[view.pickUpButton bk_addEventHandler:^(id sender) {
//							@strongify(self)
//							[self performSegueForPassengerListWithObject: nextBean isPickUp:YES isDropOff: NO];
//						} forControlEvents:UIControlEventTouchUpInside];
//					}
//					if (nextBean.scheduleStop.isPickUp && nextBean.scheduleStop.checkInPassengerNum > 0) {
//						[view.checkInButton bk_addEventHandler:^(id sender) {
//							@strongify(self)
//							[self performSegueForPassengerListWithObject: nextBean isPickUp:YES isDropOff: NO];
//						} forControlEvents:UIControlEventTouchUpInside];
//					}
//					if (nextBean.scheduleStop.isPickUp && nextBean.scheduleStop.uncheckedPassengerNum > 0) {
//						[view.uncheckedButton bk_addEventHandler:^(id sender) {
//							@strongify(self)
//							[self performSegueForPassengerListWithObject: nextBean isPickUp:YES isDropOff: NO];
//						} forControlEvents:UIControlEventTouchUpInside];
//					}
//					if (nextBean.scheduleStop.isDropOff && nextBean.scheduleStop.dropOffPassengerNum > 0) {
//						[view.dropOffButton bk_addEventHandler:^(id sender) {
//							@strongify(self)
//							[self performSegueForPassengerListWithObject: nextBean isPickUp:NO isDropOff: YES];
//						} forControlEvents:UIControlEventTouchUpInside];
//					}
//				}
//			}
//		}
//#endif
//	}

	[self showAnnotationsByScheduleStops];
	[self drawDirectionsByScheduleStops];
}

#pragma mark - Property

- (NSArray *)scheduleStops {
	return [self.busStatusDetailResponse.resultList valueForKeyPath:@"scheduleStop"];
}

#pragma mark - Segue

#ifndef TARGET_OF_Chinatown_Bus

- (void)performSegueForPassengerListWithObject:(BusStatusDetailBean *)bean isPickUp:(BOOL)isPickUp isDropOff:(BOOL)isDropOff {
	SchedulePassengerListViewController *viewController = [[SchedulePassengerListViewController alloc] init];
	viewController.service_date = self.departureDate;
    viewController.scheduleId = self.schedule.id;
	viewController.scheduleStopId = bean.scheduleStop.id;
	viewController.isPickUp = isPickUp;
	viewController.isDropOff = isDropOff;
	if ([Vars appDelegate].loginUser.is_vendor) {
		viewController.allowsCheckIn = YES;
	} else if ([Vars appDelegate].loginUser.is_bus_driver && bean.driverAssigned) {
		viewController.allowsCheckIn = YES;
	}
	[self.navigationController pushViewController:viewController animated:YES];
}

#endif

#pragma mark - Private

- (void)showAnnotationsByScheduleStops {
	[self.scheduleStops enumerateObjectsUsingBlock:^(ScheduleStop *scheduleStop, NSUInteger idx, BOOL *stop) {
		PointAnnotation *annotation = [[PointAnnotation alloc] init];
		annotation.coordinate = CLLocationCoordinate2DMake(scheduleStop.busstation.latitude, scheduleStop.busstation.longitude);
		annotation.title = scheduleStop.busstation.destination.show_name;
		annotation.subtitle = scheduleStop.busstation.name;
		if (idx == self.scheduleStops.count - 1) {
			annotation.image = [UIImage imageNamed:@"icon_bus_station_arrival"];
		} else {
			annotation.image = [UIImage imageNamed:@"icon_bus_station_departure"];
		}
		[self.mutableAnnotations addObject:annotation];
	}];
	[self.mapView addAnnotations:self.mutableAnnotations];
	[self.mapView showAnnotations:self.mutableAnnotations animated:NO];
	if (self.busStatusDetailResponse.currentLocation) {
		[self showAnnotationToGeocodeLocationWithCoordinate:CLLocationCoordinate2DMake(self.busStatusDetailResponse.currentLocation.latitude, self.busStatusDetailResponse.currentLocation.longitude) timestamp:[DateUtils parseDate:self.busStatusDetailResponse.currentLocation.updateTime parsePatterns:@"yyyy-MM-dd'T'HH:mm:ssZZ", nil]];
	}
}

- (void)drawDirectionsByScheduleStops {
	NSMutableArray *locations = [NSMutableArray array];
	for (ScheduleStop *scheduleStop in self.scheduleStops) {
		[locations addObject:[[CLLocation alloc] initWithLatitude:scheduleStop.busstation.latitude longitude:scheduleStop.busstation.longitude]];
	}
	if (self.busStatusDetailResponse.currentLocation && self.busStatusDetailResponse.currentIndex >= 0 && self.busStatusDetailResponse.currentIndex < self.scheduleStops.count - 1) {
		[locations insertObject:[[CLLocation alloc] initWithLatitude:self.busStatusDetailResponse.currentLocation.latitude longitude:self.busStatusDetailResponse.currentLocation.longitude] atIndex:self.busStatusDetailResponse.currentIndex + 1];
	}
	[locations enumerateObjectsUsingBlock:^(CLLocation *location, NSUInteger idx, BOOL *stop) {
		if (idx < locations.count - 1) {
			CLLocation *nextLocation = locations[idx + 1];
			[self drawDirectionFromCoordinate:location.coordinate toCoordinate:nextLocation.coordinate completionHandler:^(MKRoute *route) {
				if (self.busStatusDetailResponse.currentLocation) {
				} else if (idx == self.busStatusDetailResponse.stopIndex) {
					[self traverseDistanceWithRoute:route];
				}
			}];
		}
	}];
}

- (void)drawDirectionFromCoordinate:(CLLocationCoordinate2D)sourceCoordinate toCoordinate:(CLLocationCoordinate2D)destinationCoordinate completionHandler:(void (^) (MKRoute *route))completionHandler {
	MKPlacemark *sourcePlacemark = [[MKPlacemark alloc] initWithCoordinate:sourceCoordinate addressDictionary:nil];
	MKPlacemark *destinationPlacemark = [[MKPlacemark alloc] initWithCoordinate:destinationCoordinate addressDictionary:nil];
	MKMapItem *sourceMapItem = [[MKMapItem alloc] initWithPlacemark:sourcePlacemark];
	MKMapItem *destinationMapItem = [[MKMapItem alloc] initWithPlacemark:destinationPlacemark];
	MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
	request.source = sourceMapItem;
	request.destination = destinationMapItem;
	request.requestsAlternateRoutes = YES;
	MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
	[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
		if (response) {
			NSArray<MKRoute *> *routes = nil;
			if ([SystemUtils isOperatingSystemAtLeastVersion:NSOperatingSystemVersionMake(9, 0, 0)]) {
				routes = [response.routes bk_select:^BOOL (MKRoute *route) {
					return route.transportType == MKDirectionsTransportTypeTransit;
				}];
			}
			if (routes.count == 0) {
				routes = [response.routes bk_select:^BOOL (MKRoute *route) {
					return route.transportType == MKDirectionsTransportTypeAutomobile;
				}];
			}
			if (routes.count > 1) {
				routes = [routes sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"expectedTravelTime" ascending:YES], [NSSortDescriptor sortDescriptorWithKey:@"distance" ascending:YES]]];
			}
			MKRoute *route = routes.count > 0 ? routes[0] : nil;
			if (route) {
				[self.mapView addOverlay:route.polyline];
				if (completionHandler) {
					completionHandler(route);
				}
			}
		}
	}];
}

- (void)traverseDistanceWithRoute:(MKRoute *)route {
	CGFloat travelDistance = route.distance * self.busStatusDetailResponse.stopProgress;
	__block CGFloat distance = 0;
	[route.steps enumerateObjectsUsingBlock:^(MKRouteStep *step, NSUInteger idx, BOOL *stop) {
		distance += step.distance;
		if (distance >= travelDistance) {
			[self selectAnnotationWithRouteStep:step];
			*stop = YES;
			return;
		}
	}];
}

- (void)selectAnnotationWithRouteStep:(MKRouteStep *)step {
	CLLocationCoordinate2D *coordinates = malloc(sizeof(CLLocationCoordinate2D) * step.polyline.pointCount);
	[step.polyline getCoordinates:coordinates range:NSMakeRange(0, step.polyline.pointCount)];
	CLLocationCoordinate2D coordinate = coordinates[0];
	[self showAnnotationToGeocodeLocationWithCoordinate:coordinate timestamp:[NSDate date]];
	free(coordinates);
}

- (void)showAnnotationToGeocodeLocationWithCoordinate:(CLLocationCoordinate2D)coordinate timestamp:(NSDate *)timestamp {
	[Utility reverseGeocodeLocation:[[CLLocation alloc] initWithLatitude:coordinate.latitude longitude:coordinate.longitude] completionHandler:^(CLPlacemark *placemark, NSError *error) {
		PointAnnotation *annotation = [[PointAnnotation alloc] init];
		annotation.coordinate = coordinate;
		annotation.image = [UIImage imageNamed:@"icon_bus_carrier_online"];
		annotation.attributedTitle = [BusStatusApi attributedStringForBusStatusLocationWithPlacemark:placemark timestamp:timestamp product:self.product schedule:self.schedule];
		[self.mutableAnnotations addObject:annotation];
		[self.mapView addAnnotation:annotation];
		[self.mapView showAnnotations:self.mutableAnnotations animated:NO];
		[self.mapView selectAnnotation:annotation animated:YES];
	}];
}

#pragma mark - Map view delegate

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
	if (![annotation isKindOfClass:[PointAnnotation class]]) {
		return nil;
	}
	PointAnnotation *marker = annotation;
	static NSString *PinIdentifier = @"Pin";
	MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:PinIdentifier];
	if (!annotationView) {
		annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:PinIdentifier];
	}
	annotationView.canShowCallout = NO;
	annotationView.image = marker.image;
	if (annotationView.image) {
		annotationView.centerOffset = CGPointMake(0, -annotationView.image.size.height / 2);
	} else {
		annotationView.centerOffset = CGPointZero;
	}
	return annotationView;
}

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
	if ([NSStringFromClass(view.class) isEqualToString:@"MKModernUserLocationView"]) {
		return;
	}
	if (![view.annotation isKindOfClass:[PointAnnotation class]]) {
		return;
	}
	PointAnnotation *marker = view.annotation;
	SMModernCalloutView *calloutView = ((SMMapView *) mapView).calloutView;
	[CocoaUtils configureCalloutView:calloutView annotation:marker];
	[calloutView presentCalloutFromRect:view.bounds inView:view constrainedToView:mapView animated:YES];
}

- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view {
	if ([NSStringFromClass(view.class) isEqualToString:@"MKModernUserLocationView"]) {
		return;
	}
	if (![view.annotation isKindOfClass:[PointAnnotation class]]) {
		return;
	}
	SMModernCalloutView *calloutView = ((SMMapView *) mapView).calloutView;
	[calloutView dismissCalloutAnimated:YES];
}

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)overlay {
	MKPolylineRenderer *line = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
	line.lineWidth = 5;
	line.strokeColor = [UIColor aquaColor];
	return line;
}

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray<MKAnnotationView *> *)views {
	for (MKAnnotationView *view in views) {
		if ([NSStringFromClass(view.class) isEqualToString:@"MKModernUserLocationView"]) {
			view.canShowCallout = NO;
		}
	}
}

@end
