//
//  UIViewController+ChildSwitch.m
//  segmentSwitch
//
//  Created by wangyang on 5/13/15.
//  Copyright (c) 2015 IGIU. All rights reserved.
//

#import "UIViewController+ChildControllerSwitch.h"
#import <objc/runtime.h>
#import <Masonry/Masonry.h>
#import "UIView+Layout.h"
#import "Constant.h"
@interface NSObject (CustomClass)

@end
@implementation NSObject (CustomClass)
@end

@interface ScrollViewDelegate: NSObject <UIScrollViewDelegate>
@property (nonatomic, copy) void (^scrollViewEndScroll) (void);

@end

@implementation ScrollViewDelegate
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    if (self.scrollViewEndScroll) {
        self.scrollViewEndScroll();
    }
}
@end

@interface UIViewController ()

@property (nonatomic, strong) ScrollViewDelegate *scrollDelegate;
@end
@implementation UIViewController (ChildControllerSwitch)

/**
 *  set方法是为了适应IB,如果纯代码可以不用set方法
 */
- (void)setChildContainer:(UIView *)childContainer{
    objc_setAssociatedObject(self, @selector(childContainer), childContainer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (UIView *)childContainer{
    UIView *childContainer = objc_getAssociatedObject(self, _cmd);
    if (!childContainer) {
        childContainer = [[UIView alloc] init];
        childContainer.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        objc_setAssociatedObject(self, _cmd, childContainer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return childContainer;
}

- (void)setCurrentController:(UIViewController *)currentController{
    objc_setAssociatedObject(self, NSSelectorFromString(@"currentController"), currentController, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (UIViewController *)currentController{
    return objc_getAssociatedObject(self, NSSelectorFromString(@"currentController"));
}

- (void)setChildScrollView:(UIScrollView *)childScrollView {
    objc_setAssociatedObject(self, @selector(childScrollView), childScrollView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (UIScrollView *)childScrollView {
    UIScrollView *_childScrollView = objc_getAssociatedObject(self, @selector(childScrollView));
    if (_childScrollView == nil) {
        _childScrollView = [UIScrollView new];
        _childScrollView.delegate = self.scrollDelegate;
        _childScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        [self.childContainer addSubview:_childScrollView];
        _childScrollView.pagingEnabled = YES;
        _childScrollView.scrollsToTop = NO;
        _childScrollView.showsHorizontalScrollIndicator = NO;
        [_childScrollView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.edges.mas_equalTo(UIEdgeInsetsZero);
        }];
        objc_setAssociatedObject(self, _cmd, _childScrollView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return _childScrollView;
}

- (void)setScrollDelegate:(ScrollViewDelegate *)scrollDelegate {
    objc_setAssociatedObject(self, @selector(scrollDelegate), scrollDelegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (ScrollViewDelegate *)scrollDelegate {
    ScrollViewDelegate *_scrollDelegate = objc_getAssociatedObject(self, @selector(scrollDelegate));
    if (_scrollDelegate == nil) {
        _scrollDelegate = [ScrollViewDelegate new];
        __weak __typeof(self) weakSelf = self;
        _scrollDelegate.scrollViewEndScroll = ^{
            [weakSelf prepareChangeController];
        };
        objc_setAssociatedObject(self, _cmd, _scrollDelegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return _scrollDelegate;
}


- (void)setChildContainerSize:(CGSize)childContainerSize {
    NSValue *size = [NSValue valueWithCGSize:childContainerSize];
    objc_setAssociatedObject(self, @selector(childContainerSize), size, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    if (self.childs.count != 0) {
        #warning 这个高度是否可以直接使用self.height
        self.childScrollView.contentSize = CGSizeMake(childContainerSize.width * self.childs.count , childContainerSize.height);
    }
}

- (CGSize)childContainerSize {
    NSValue *size = objc_getAssociatedObject(self, @selector(childContainerSize));
    if (size == nil) {
        return CGSizeZero;
    } else {
        return [size CGSizeValue];
    }
}

- (void)setChildScrollViewDidEndScroll:(void (^) (NSInteger))block {
    objc_setAssociatedObject(self, @selector(childScrollViewDidEndScroll), block, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (void (^) (NSInteger))childScrollViewDidEndScroll {
    id block = objc_getAssociatedObject(self, @selector(childScrollViewDidEndScroll));
    return block;
}

- (void)setChilds:(NSArray *)childs {
    objc_setAssociatedObject(self, @selector(childs), childs, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSArray *)childs {
    NSArray *_childs = objc_getAssociatedObject(self, @selector(childs));
    return _childs;
}

- (void)setDidFinishSwitchChild:(void (^) (void))block {
    objc_setAssociatedObject(self, @selector(didFinishSwitchChild), block, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (void (^) (void))didFinishSwitchChild {
    id block = objc_getAssociatedObject(self, @selector(didFinishSwitchChild));
    return block;
}

#pragma mark - 方法
- (void)setFirstController:(UIViewController *)controller {
    [self addForwardAppearanceMethods:controller];
    self.childContainer.size = self.childContainerSize;
    self.childScrollView.size = self.childContainerSize;
    controller.view.frame = self.childContainer.bounds;
    controller.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    [self.childScrollView addSubview:controller.view];
    self.currentController = controller;
    [self addChildViewController:controller];
    [self.currentController didMoveToParentViewController:self];
}

- (void)setFirstController:(UIViewController *)controller otherController:(NSArray *)otherControllers {
    NSAssert(controller, @"不能设置nil为第一个controller");
    NSAssert(self.childContainer.superview, @"self.childContainer must have a superview");
    [self setFirstController:controller];
    [self addOtherController:otherControllers];
 
}
- (void)addOtherController:(NSArray *)otherControllers {
    NSAssert(self.currentController, @"不能设置nil为第一个controller");
    for (UIViewController *other in otherControllers) {
        [self addForwardAppearanceMethods:other];
        [self addChildViewController:other];
    }
    self.childs = [[NSArray arrayWithObject:self.currentController] arrayByAddingObjectsFromArray:otherControllers];
    CGSize size = CGSizeMake(self.childContainerSize.width * self.childs.count , self.childContainerSize.height);
    self.childScrollView.contentSize = size;
}

- (void)addForwardAppearanceMethods:(UIViewController *)controller {
    SEL sel = @selector(shouldAutomaticallyForwardAppearanceMethods);
    IMP imp = imp_implementationWithBlock(^(){
        return NO;
    });
    class_addMethod([controller class], sel, imp, "B@:");
}

- (void)switchToChildControllerAtIndex:(NSUInteger)index {
    self.childScrollView.contentOffset = CGPointMake(index * self.childContainer.bounds.size.width, 0);

    /*
     比如A -> B -> A，因为A.view被添加到scrollView中就不会被移除，所以当再次回到A->B，或者B->A时，viewWillAppear等4个方法都不会调用
     使用 beginAppearanceTransition:animated:、endAppearanceTransition 可以解决这个问题。
     另外需要配合 shouldAutomaticallyForwardAppearanceMethods 使用。

     beginAppearanceTransition:animated: 设置为YES触发Child View Controller的viewWillAppear;
     beginAppearanceTransition:animated: 设置为NO触发Child View Controller的viewWillDisappear;
     endAppearanceTransition 触发Child View Controller的viewDidAppear 和viewDidDisappear
     */
    UIViewController *to  = self.childViewControllers[index];
    UIViewController *from = self.currentController;
    if (to == from) {
        if (self.didFinishSwitchChild) {
            self.didFinishSwitchChild();
        }
    } else {
        if (to.view.superview == nil) {
            CGRect frame = self.childContainer.bounds;
            frame.origin.x = frame.size.width * index;
            frame.size = self.childContainer.size;
            to.view.frame = frame;
            to.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
            [self.childScrollView addSubview:to.view];
            [from beginAppearanceTransition:NO animated:NO];
            [to didMoveToParentViewController:self];
            [from endAppearanceTransition];
        } else {
            [to beginAppearanceTransition:YES animated:NO];
            [from beginAppearanceTransition:NO animated:NO];
            [to endAppearanceTransition];
            [from endAppearanceTransition];
        }

        self.currentController = to;
        if (self.didFinishSwitchChild) {
            self.didFinishSwitchChild();
        }
    }
}

- (void)prepareChangeController {
    int index = self.childScrollView.contentOffset.x / self.childContainer.bounds.size.width;
    [self switchToChildControllerAtIndex:index];
    if (self.childScrollViewDidEndScroll) {
        self.childScrollViewDidEndScroll(index);
    }
}

@end
