//
//  SystemActions.m
//
//

#import "SystemActions.h"
#import "AppDelegate.h"

@protocol SceneInputDataSource <NSObject>
- (void)setContents:(id)contents indexPath:(NSIndexPath *)indexPath originalDataSource:(id)originalDataSource;
@end

@protocol ViewControllerWithSceneInputDataSource <NSObject>
- (id<SceneInputDataSource>)sceneInputDataSource;
@end

@protocol ViewControllerWithModalInterfaceOrientations <NSObject>
- (NSUInteger)supportedModalInterfaceOrientations;
@end

@protocol ViewControllerWithSceneID <NSObject>
- (NSString *)originalSceneID;
@end

@implementation SystemActions

+ (UIViewController*)topMostController
{
    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
	
    while (topController.presentedViewController) {
        topController = topController.presentedViewController;
    }
	
    return topController;
}

+ (UITabBarController *)tabBarController {
	
	UIViewController * topMostController = self.topMostController;
	
	if ([topMostController isKindOfClass:[UITabBarController class]]) return (UITabBarController *)topMostController;
	
	return topMostController.tabBarController;
}


#pragma mark - Navigation

+ (void)goToScene:(NSString *)interfaceBuilderSceneIdentifier {
	[self goToScene:interfaceBuilderSceneIdentifier fromController:nil animated:NO usingTransition:0];
}

+ (void)goToScene:(NSString *)interfaceBuilderSceneIdentifier fromController:(id)controller usingTransition:(UIModalTransitionStyle)transitionStyle {
	[self goToScene:interfaceBuilderSceneIdentifier fromController:controller animated:YES usingTransition:transitionStyle];
}

+ (void)goToScene:(NSString *)interfaceBuilderSceneIdentifier fromController:(id)controller animated:(BOOL)animated usingTransition:(UIModalTransitionStyle)transitionStyle {
	
	[self goToScene:interfaceBuilderSceneIdentifier fromController:(id)controller withContextData:nil animated:animated usingTransition:transitionStyle];

}

+ (void)goToScene:(NSString *)interfaceBuilderSceneIdentifier fromController:(id)controller withContextData:(id)data animated:(BOOL)animated usingTransition:(UIModalTransitionStyle)transitionStyle {

	UIViewController * topMostController = nil;
	if ([controller isKindOfClass:[UIViewController class]]) topMostController = controller;
	if (!topMostController) topMostController = self.topMostController;
	
	if (!data) {
		// Select the tab in a tab bar, if possible
		UITabBarController * tabBarController = self.tabBarController;
		if (tabBarController && transitionStyle < 0) {
			for (UIViewController * vc in tabBarController.childViewControllers) {
				UIViewController * childViewController = vc;
				if ([childViewController isKindOfClass:[UINavigationController class]]) {
					childViewController = [(UINavigationController *)childViewController topViewController];
				}
				if ([childViewController respondsToSelector:@selector(originalSceneID)]) {
					if ([[(UIViewController <ViewControllerWithSceneID>*)childViewController originalSceneID] isEqualToString:interfaceBuilderSceneIdentifier]) {
						tabBarController.selectedViewController = vc;
						return;
					}
				}
			}
		}
		
		// Go back, if possible
		UINavigationController * nc = [self navigationControllerForController:topMostController];
		if (transitionStyle < 0 && nil != nc) {
			if (nc.viewControllers.count > 1) {
				for (UIViewController * viewController in nc.viewControllers) {
					NSString * sceneID = [((UIViewController <ViewControllerWithSceneID> *)viewController) originalSceneID];
					if ([sceneID isEqualToString:interfaceBuilderSceneIdentifier]) {
						[nc popToViewController:viewController animated:YES];
						return;
					}
				}
			}
		}
		
		// Dismiss the modal view controller, if possible
		if (topMostController.presentingViewController && transitionStyle < 0) {
			UIViewController * vc = topMostController.presentingViewController;
			if ([vc isKindOfClass:[UITabBarController class]]) {
				vc = ((UITabBarController *)vc).selectedViewController;
			}
			if ([vc isKindOfClass:[UINavigationController class]]) {
				vc = ((UINavigationController *)vc).topViewController;
			}
			if ([vc respondsToSelector:@selector(originalSceneID)]) {
				NSString * sceneID = [((UIViewController <ViewControllerWithSceneID> *)vc) originalSceneID];
				if ([sceneID isEqualToString:interfaceBuilderSceneIdentifier]) {
					[topMostController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
					return;
				}
			}
		}
	}

	UIViewController * targetViewController = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:interfaceBuilderSceneIdentifier];
	
	UIViewController * topController = targetViewController;
	if ([targetViewController isKindOfClass:[UINavigationController class]]) topController = ((UINavigationController *)topController).topViewController;

	if ([topController respondsToSelector:@selector(sceneInputDataSource)]) {
		id<SceneInputDataSource> sceneInputDataSource = [topController valueForKey:@"sceneInputDataSource"];
		[sceneInputDataSource setContents:data indexPath:nil originalDataSource:nil];
	}
	
	NSUInteger supportedInterfaceOrientations = 0;
	if ([topController respondsToSelector:@selector(supportedModalInterfaceOrientations)]) {
		supportedInterfaceOrientations = [[topController valueForKey:@"supportedModalInterfaceOrientations"] unsignedIntegerValue];
	}


	[self navigateToViewController:targetViewController fromViewController:topMostController animated:animated modalTransitionStyle:transitionStyle];
	[(AppDelegate *)[[UIApplication sharedApplication] delegate] setCurrentSupportedInterfaceOrientations:supportedInterfaceOrientations];
}

+ (UINavigationController *)navigationControllerForController:(UIViewController *)controller {
	if ([controller isKindOfClass:[UINavigationController class]]) {
		return (UINavigationController *)controller;
	}
	if ([controller isKindOfClass:[UITabBarController class]]) {
		return [self navigationControllerForController:((UITabBarController *)controller).selectedViewController];
	}
	return controller.navigationController;
}

+ (void)navigateToViewController:(UIViewController *)targetViewController fromViewController:(UIViewController *)topMostController animated:(BOOL)animated modalTransitionStyle:(UIModalTransitionStyle)transitionStyle {
	
	targetViewController.modalTransitionStyle = transitionStyle;
	
	if ([topMostController isKindOfClass:[UITabBarController class]]) {
		topMostController = ((UITabBarController *)topMostController).selectedViewController;
	}
	if (topMostController.navigationController) topMostController = topMostController.navigationController;
	
	if ([topMostController isKindOfClass:[UINavigationController class]] && transitionStyle < 0) {
		UINavigationController * nc = (UINavigationController *)topMostController;
		if ([targetViewController isKindOfClass:[UINavigationController class]]) {
			targetViewController = [((UINavigationController *)targetViewController) topViewController];
		}
		[nc pushViewController:targetViewController animated:YES];
		return;
	}
	
	if (targetViewController.navigationItem && ![targetViewController isKindOfClass:[UINavigationController class]]) {
		UINavigationController * navigationController = [[UINavigationController alloc] initWithRootViewController:targetViewController];

		targetViewController = navigationController;
	}


	[topMostController presentViewController:targetViewController animated:animated completion:0];
	
}

+ (void)navigateBackFromViewController:(UIViewController *)viewController {
	
	[(AppDelegate *)[[UIApplication sharedApplication] delegate] setCurrentSupportedInterfaceOrientations:0];
	
	if (viewController.navigationController && viewController.navigationController.viewControllers.count > 1)
		[viewController.navigationController popViewControllerAnimated:YES];
	
	else [viewController dismissViewControllerAnimated:YES completion:nil];


}

#pragma mark - View movement

+ (void)moveView:(UIView *)view toPosition:(CGPoint)position animated:(BOOL)animated {
	if (animated) [UIView beginAnimations:@"" context:NULL];
	CGRect newFrame = view.frame;
	newFrame.origin = position;
	view.frame = newFrame;
	if (animated) [UIView commitAnimations];
}

@end
