//
// WEPopoverController.m
// WEPopover
//
// Created by Werner Altewischer on 02/09/10.
// Copyright 2010 Werner IT Consultancy. All rights reserved.
//

#import "WEPopoverController.h"
#import "WEPopoverParentView.h"
#import "UIBarButtonItem+WEPopover.h"

#define FADE_DURATION 0.3

@interface WEPopoverController(Private)

- (UIView *)keyView;
- (void)updateBackgroundPassthroughViews;
- (void)setView:(UIView *)v;
- (CGRect)displayAreaForView:(UIView *)theView;
- (WEPopoverContainerViewProperties *)defaultContainerViewProperties;
- (void)dismissPopoverAnimated:(BOOL)animated userInitiated:(BOOL)userInitiated;

@end

@implementation WEPopoverController

@synthesize contentViewController;
@synthesize popoverContentSize;
@synthesize popoverVisible;
@synthesize popoverArrowDirection;
@synthesize delegate;
@synthesize view;
@synthesize parentView;
@synthesize containerViewProperties;
@synthesize context;
@synthesize passthroughViews;

- (id)init {
if ((self = [super init])) {
}
return self;
}

- (id)initWithContentViewController:(UIViewController *)viewController {
if ((self = [self init])) {
self.contentViewController = viewController;
}
return self;
}

- (void)dealloc {
[self dismissPopoverAnimated:NO];
[contentViewController release];
[containerViewProperties release];
[passthroughViews release];
self.context = nil;
[super dealloc];
}

- (void)setContentViewController:(UIViewController *)vc {
if (vc != contentViewController) {
[contentViewController release];
contentViewController = [vc retain];
popoverContentSize = CGSizeZero;
}
}

- (BOOL)forwardAppearanceMethods {
return ![contentViewController respondsToSelector:@selector(automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers)];
}

//Overridden setter to copy the passthroughViews to the background view if it exists already
- (void)setPassthroughViews:(NSArray *)array {
[passthroughViews release];
passthroughViews = nil;
if (array) {
passthroughViews = [[NSArray alloc] initWithArray:array];
}
[self updateBackgroundPassthroughViews];
}

- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)theContext {

if ([animationID isEqual:@"FadeIn"]) {
self.view.userInteractionEnabled = YES;
popoverVisible = YES;

if ([self forwardAppearanceMethods]) {
[contentViewController viewDidAppear:YES];
}
} else if ([animationID isEqual:@"FadeOut"]) {
popoverVisible = NO;

if ([self forwardAppearanceMethods]) {
[contentViewController viewDidDisappear:YES];
}
[self.view removeFromSuperview];
self.view = nil;
[backgroundView removeFromSuperview];
[backgroundView release];
backgroundView = nil;

BOOL userInitiatedDismissal = [(NSNumber *)theContext boolValue];

if (userInitiatedDismissal) {
//Only send message to delegate in case the user initiated this event, which is if he touched outside the view
[delegate popoverControllerDidDismissPopover:self];
}
}
}

- (void)dismissPopoverAnimated:(BOOL)animated {

[self dismissPopoverAnimated:animated userInitiated:NO];
}

- (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)item
permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections
animated:(BOOL)animated {

UIView *v = [self keyView];
CGRect rect = [item frameInView:v];

return [self presentPopoverFromRect:rect inView:v permittedArrowDirections:arrowDirections animated:animated];
}

- (void)presentPopoverFromRect:(CGRect)rect
inView:(UIView *)theView
permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections
animated:(BOOL)animated {

[self dismissPopoverAnimated:NO];

//First force a load view for the contentViewController so the popoverContentSize is properly initialized
[contentViewController view];

if (CGSizeEqualToSize(popoverContentSize, CGSizeZero)) {
popoverContentSize = contentViewController.contentSizeForViewInPopover;
}

CGRect displayArea = [self displayAreaForView:theView];

WEPopoverContainerViewProperties *props = self.containerViewProperties ? self.containerViewProperties : [self defaultContainerViewProperties];
WEPopoverContainerView *containerView = [[[WEPopoverContainerView alloc] initWithSize:self.popoverContentSize anchorRect:rect displayArea:displayArea permittedArrowDirections:arrowDirections properties:props] autorelease];
popoverArrowDirection = containerView.arrowDirection;

UIView *keyView = self.keyView;

backgroundView = [[WETouchableView alloc] initWithFrame:keyView.bounds];
backgroundView.contentMode = UIViewContentModeScaleToFill;
backgroundView.autoresizingMask = ( UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleTopMargin |
UIViewAutoresizingFlexibleHeight |
UIViewAutoresizingFlexibleBottomMargin);
backgroundView.backgroundColor = [UIColor clearColor];
backgroundView.delegate = self;

[keyView addSubview:backgroundView];

containerView.frame = [theView convertRect:containerView.frame toView:backgroundView];

[backgroundView addSubview:containerView];

containerView.contentView = contentViewController.view;
containerView.autoresizingMask = ( UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin);

self.view = containerView;
[self updateBackgroundPassthroughViews];

if ([self forwardAppearanceMethods]) {
[contentViewController viewWillAppear:animated];
}
[self.view becomeFirstResponder];
popoverVisible = YES;
if (animated) {
self.view.alpha = 0.0;

[UIView animateWithDuration:FADE_DURATION
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{

self.view.alpha = 1.0;

} completion:^(BOOL finished) {

[self animationDidStop:@"FadeIn" finished:[NSNumber numberWithBool:finished] context:nil];
}];

} else {
if ([self forwardAppearanceMethods]) {
[contentViewController viewDidAppear:animated];
}
}
}

- (void)repositionPopoverFromRect:(CGRect)rect
inView:(UIView *)theView
permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections
{

[self repositionPopoverFromRect:rect
inView:theView
permittedArrowDirections:arrowDirections
animated:NO];
}

- (void)repositionPopoverFromRect:(CGRect)rect
inView:(UIView *)theView
permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections
animated:(BOOL)animated {

if (animated) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:FADE_DURATION];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
}

if (CGSizeEqualToSize(popoverContentSize, CGSizeZero)) {
popoverContentSize = contentViewController.contentSizeForViewInPopover;
}

CGRect displayArea = [self displayAreaForView:theView];
WEPopoverContainerView *containerView = (WEPopoverContainerView *)self.view;
[containerView updatePositionWithSize:self.popoverContentSize
anchorRect:rect
displayArea:displayArea
permittedArrowDirections:arrowDirections];

popoverArrowDirection = containerView.arrowDirection;
containerView.frame = [theView convertRect:containerView.frame toView:backgroundView];

if (animated) {
[UIView commitAnimations];
}
}

#pragma mark -
#pragma mark WETouchableViewDelegate implementation

- (void)viewWasTouched:(WETouchableView *)view {
if (popoverVisible) {
if (!delegate || [delegate popoverControllerShouldDismissPopover:self]) {
[self dismissPopoverAnimated:YES userInitiated:YES];
}
}
}

- (BOOL)isPopoverVisible {
if (!popoverVisible) {
return NO;
}
UIView *sv = self.view;
BOOL foundWindowAsSuperView = NO;
while ((sv = sv.superview) != nil) {
if ([sv isKindOfClass:[UIWindow class]]) {
foundWindowAsSuperView = YES;
break;
}
}
return foundWindowAsSuperView;
}

@end

@implementation WEPopoverController(Private)

- (UIView *)keyView {
if (self.parentView) {
return self.parentView;
} else {
UIWindow *w = [[UIApplication sharedApplication] keyWindow];
if (w.subviews.count > 0) {
return [w.subviews objectAtIndex:0];
} else {
return w;
}
}
}

- (void)setView:(UIView *)v {
if (view != v) {
[view release];
view = [v retain];
}
}

- (void)updateBackgroundPassthroughViews {
backgroundView.passthroughViews = passthroughViews;
}

- (void)dismissPopoverAnimated:(BOOL)animated userInitiated:(BOOL)userInitiated {
if (self.view) {
if ([self forwardAppearanceMethods]) {
[contentViewController viewWillDisappear:animated];
}
popoverVisible = NO;
[self.view resignFirstResponder];
if (animated) {
self.view.userInteractionEnabled = NO;

[UIView animateWithDuration:FADE_DURATION
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{

self.view.alpha = 0.0;

} completion:^(BOOL finished) {

[self animationDidStop:@"FadeOut" finished:[NSNumber numberWithBool:finished] context:[NSNumber numberWithBool:userInitiated]];
}];

} else {
if ([self forwardAppearanceMethods]) {
[contentViewController viewDidDisappear:animated];
}
[self.view removeFromSuperview];
self.view = nil;
[backgroundView removeFromSuperview];
[backgroundView release];
backgroundView = nil;
}
}
}

- (CGRect)displayAreaForView:(UIView *)theView {
CGRect displayArea = CGRectZero;
if ([theView conformsToProtocol:@protocol(WEPopoverParentView)] && [theView respondsToSelector:@selector(displayAreaForPopover)]) {
displayArea = [(id <WEPopoverParentView>)theView displayAreaForPopover];
} else {
UIView *keyView = [self keyView];
displayArea = [keyView convertRect:keyView.bounds toView:theView];
}
return displayArea;
}

//Enable to use the simple popover style
- (WEPopoverContainerViewProperties *)defaultContainerViewProperties {
WEPopoverContainerViewProperties *ret = [[WEPopoverContainerViewProperties new] autorelease];

CGSize imageSize = CGSizeMake(30.0f, 30.0f);
NSString *bgImageName = @"popoverBgSimple.png";
CGFloat bgMargin = 6.0;
CGFloat contentMargin = 2.0;

ret.leftBgMargin = bgMargin;
ret.rightBgMargin = bgMargin;
ret.topBgMargin = bgMargin;
ret.bottomBgMargin = bgMargin;
ret.leftBgCapSize = imageSize.width/2;
ret.topBgCapSize = imageSize.height/2;
ret.bgImageName = bgImageName;
ret.leftContentMargin = contentMargin;
ret.rightContentMargin = contentMargin;
ret.topContentMargin = contentMargin;
ret.bottomContentMargin = contentMargin;
ret.arrowMargin = 1.0;

ret.upArrowImageName = @"popoverArrowUpSimple.png";
ret.downArrowImageName = @"popoverArrowDownSimple.png";
ret.leftArrowImageName = @"popoverArrowLeftSimple.png";
ret.rightArrowImageName = @"popoverArrowRightSimple.png";
return ret;
}

@end