#import "RCCTabBarController.h"
#import "RCCViewController.h"
#import <React/RCTConvert.h>
#import "RCCManager.h"
#import "RCTHelpers.h"
#import <React/RCTUIManager.h>
#import "UIViewController+Rotation.h"

@interface RCTUIManager ()

- (void)configureNextLayoutAnimation:(NSDictionary *)config
                        withCallback:(RCTResponseSenderBlock)callback
                       errorCallback:(__unused RCTResponseSenderBlock)errorCallback;

@end

@implementation RCCTabBarController


-(UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return [self supportedControllerOrientations];
}

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
    id queue = [[RCCManager sharedInstance].getBridge uiManager].methodQueue;
    dispatch_async(queue, ^{
        [[[RCCManager sharedInstance].getBridge uiManager] configureNextLayoutAnimation:nil withCallback:^(NSArray* arr){} errorCallback:^(NSArray* arr){}];
    });
    
    if (tabBarController.selectedIndex != [tabBarController.viewControllers indexOfObject:viewController]) {
        NSDictionary *body = @{
                               @"selectedTabIndex": @([tabBarController.viewControllers indexOfObject:viewController]),
                               @"unselectedTabIndex": @(tabBarController.selectedIndex)
                               };
        [RCCTabBarController sendScreenTabChangedEvent:viewController body:body];
        
        [[[RCCManager sharedInstance] getBridge].eventDispatcher sendAppEventWithName:@"bottomTabSelected" body:body];
        if ([viewController isKindOfClass:[UINavigationController class]]) {
            UINavigationController *navigationController = (UINavigationController*)viewController;
            UIViewController *topViewController = navigationController.topViewController;
            
            if ([topViewController isKindOfClass:[RCCViewController class]]) {
                RCCViewController *topRCCViewController = (RCCViewController*)topViewController;
                topRCCViewController.commandType = COMMAND_TYPE_BOTTOME_TAB_SELECTED;
                topRCCViewController.timestamp = [RCTHelpers getTimestampString];
            }
        }
        
    } else {
        [RCCTabBarController sendScreenTabPressedEvent:viewController body:nil];
    }
    
    
    
    return YES;
}

- (UIImage *)image:(UIImage*)image withColor:(UIColor *)color1 {
    UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, 0, image.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextSetBlendMode(context, kCGBlendModeNormal);
    CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
    CGContextClipToMask(context, rect, image.CGImage);
    [color1 setFill];
    CGContextFillRect(context, rect);
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

- (instancetype)initWithProps:(NSDictionary *)props children:(NSArray *)children globalProps:(NSDictionary*)globalProps bridge:(RCTBridge *)bridge {
    self = [super init];
    if (!self) return nil;
    
    self.delegate = self;
    
    self.tabBar.translucent = YES; // default
    
    UIColor *buttonColor = nil;
    UIColor *selectedButtonColor = nil;
    UIColor *labelColor = nil;
    UIColor *selectedLabelColor = nil;
    NSDictionary *tabsStyle = props[@"style"];
    if (tabsStyle) {
        NSString *tabBarButtonColor = tabsStyle[@"tabBarButtonColor"];
        if (tabBarButtonColor) {
            UIColor *color = tabBarButtonColor != (id)[NSNull null] ? [RCTConvert UIColor:tabBarButtonColor] : nil;
            self.tabBar.tintColor = color;
            buttonColor = color;
            selectedButtonColor = color;
        }
        NSString *tabBarSelectedButtonColor = tabsStyle[@"tabBarSelectedButtonColor"];
        if (tabBarSelectedButtonColor) {
            UIColor *color = tabBarSelectedButtonColor != (id)[NSNull null] ? [RCTConvert UIColor:tabBarSelectedButtonColor] : nil;
            self.tabBar.tintColor = color;
            selectedButtonColor = color;
        }
        NSString *tabBarLabelColor = tabsStyle[@"tabBarLabelColor"];
        if (tabBarLabelColor) {
            UIColor *color = tabBarLabelColor != (id)[NSNull null] ? [RCTConvert UIColor:tabBarLabelColor] : nil;
            labelColor = color;
        }
        NSString *tabBarSelectedLabelColor = tabsStyle[@"tabBarSelectedLabelColor"];
        if (tabBarLabelColor) {
            UIColor *color = tabBarSelectedLabelColor != (id)[NSNull null] ? [RCTConvert UIColor:
                                                                              tabBarSelectedLabelColor] : nil;
            selectedLabelColor = color;
        }
        NSString *tabBarBackgroundColor = tabsStyle[@"tabBarBackgroundColor"];
        if (tabBarBackgroundColor) {
            UIColor *color = tabBarBackgroundColor != (id)[NSNull null] ? [RCTConvert UIColor:tabBarBackgroundColor] : nil;
            self.tabBar.barTintColor = color;
        }
        
        NSString *tabBarTranslucent = tabsStyle[@"tabBarTranslucent"];
        if (tabBarTranslucent) {
            self.tabBar.translucent = [tabBarTranslucent boolValue] ? YES : NO;
        }
        
        NSString *tabBarHideShadow = tabsStyle[@"tabBarHideShadow"];
        if (tabBarHideShadow) {
            self.tabBar.clipsToBounds = [tabBarHideShadow boolValue] ? YES : NO;
        }
    }
    
    NSMutableArray *viewControllers = [NSMutableArray array];
    
    // go over all the tab bar items
    for (NSDictionary *tabItemLayout in children) {
        // make sure the layout is valid
        if (![tabItemLayout[@"type"] isEqualToString:@"TabBarControllerIOS.Item"]) continue;
        if (!tabItemLayout[@"props"]) continue;
        
        // get the view controller inside
        if (!tabItemLayout[@"children"]) continue;
        if (![tabItemLayout[@"children"] isKindOfClass:[NSArray class]]) continue;
        if ([tabItemLayout[@"children"] count] < 1) continue;
        NSDictionary *childLayout = tabItemLayout[@"children"][0];
        UIViewController *viewController = [RCCViewController controllerWithLayout:childLayout globalProps:globalProps bridge:bridge];
        if (!viewController) continue;
        
        // create the tab icon and title
        NSString *title = tabItemLayout[@"props"][@"title"];
        UIImage *iconImage = nil;
        id icon = tabItemLayout[@"props"][@"icon"];
        if (icon) {
            iconImage = [RCTConvert UIImage:icon];
            if (buttonColor) {
                iconImage = [[self image:iconImage withColor:buttonColor] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
            }
        }
        UIImage *iconImageSelected = nil;
        id selectedIcon = tabItemLayout[@"props"][@"selectedIcon"];
        if (selectedIcon) {
            iconImageSelected = [RCTConvert UIImage:selectedIcon];
        } else {
            iconImageSelected = [RCTConvert UIImage:icon];
        }
        
        viewController.tabBarItem = [[UITabBarItem alloc] initWithTitle:title image:iconImage tag:0];
        viewController.tabBarItem.accessibilityIdentifier = tabItemLayout[@"props"][@"testID"];
        viewController.tabBarItem.selectedImage = iconImageSelected;
        
        id imageInsets = tabItemLayout[@"props"][@"iconInsets"];
        if (imageInsets && imageInsets != (id)[NSNull null]) {
            id topInset = imageInsets[@"top"];
            id leftInset = imageInsets[@"left"];
            id bottomInset = imageInsets[@"bottom"];
            id rightInset = imageInsets[@"right"];
            
            CGFloat top = topInset != (id)[NSNull null] ? [RCTConvert CGFloat:topInset] : 0;
            CGFloat left = topInset != (id)[NSNull null] ? [RCTConvert CGFloat:leftInset] : 0;
            CGFloat bottom = topInset != (id)[NSNull null] ? [RCTConvert CGFloat:bottomInset] : 0;
            CGFloat right = topInset != (id)[NSNull null] ? [RCTConvert CGFloat:rightInset] : 0;
            
            viewController.tabBarItem.imageInsets = UIEdgeInsetsMake(top, left, bottom, right);
        }
        NSMutableDictionary *unselectedAttributes = [RCTHelpers textAttributesFromDictionary:tabsStyle withPrefix:@"tabBarText" baseFont:[UIFont systemFontOfSize:10]];
        if (!unselectedAttributes[NSForegroundColorAttributeName] && labelColor) {
            unselectedAttributes[NSForegroundColorAttributeName] = labelColor;
        }
        
        [viewController.tabBarItem setTitleTextAttributes:unselectedAttributes forState:UIControlStateNormal];
        
        NSMutableDictionary *selectedAttributes = [RCTHelpers textAttributesFromDictionary:tabsStyle withPrefix:@"tabBarSelectedText" baseFont:[UIFont systemFontOfSize:10]];
        if (!selectedAttributes[NSForegroundColorAttributeName] && selectedLabelColor) {
            selectedAttributes[NSForegroundColorAttributeName] = selectedLabelColor;
        }
        
        [viewController.tabBarItem setTitleTextAttributes:selectedAttributes forState:UIControlStateSelected];
        // create badge
        NSObject *badge = tabItemLayout[@"props"][@"badge"];
        if (badge == nil || [badge isEqual:[NSNull null]]) {
            viewController.tabBarItem.badgeValue = nil;
        } else {
            viewController.tabBarItem.badgeValue = [NSString stringWithFormat:@"%@", badge];
        }
        
        [viewControllers addObject:viewController];
    }
    
    // replace the tabs
    self.viewControllers = viewControllers;
    
    NSNumber *initialTab = tabsStyle[@"initialTabIndex"];
    if (initialTab) {
        NSInteger initialTabIndex = initialTab.integerValue;
        [self setSelectedIndex:initialTabIndex];
    }
    
    [self setRotation:props];
    
    return self;
}

- (void)performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams bridge:(RCTBridge *)bridge completion:(void (^)(void))completion {
    if ([performAction isEqualToString:@"setBadge"]) {
        UIViewController *viewController = nil;
        NSNumber *tabIndex = actionParams[@"tabIndex"];
        if (tabIndex) {
            int i = (int)[tabIndex integerValue];
            
            if ([self.viewControllers count] > i) {
                viewController = [self.viewControllers objectAtIndex:i];
            }
        }
        NSString *contentId = actionParams[@"contentId"];
        NSString *contentType = actionParams[@"contentType"];
        if (contentId && contentType) {
            viewController = [[RCCManager sharedInstance] getControllerWithId:contentId componentType:contentType];
        }
        
        if (viewController) {
            NSObject *badge = actionParams[@"badge"];
            
            if (badge == nil || [badge isEqual:[NSNull null]]) {
                viewController.tabBarItem.badgeValue = nil;
            }
            else
            {
                NSString *badgeColor = actionParams[@"badgeColor"];
                UIColor *color = badgeColor != (id)[NSNull null] ? [RCTConvert UIColor:badgeColor] : nil;
                
                if ([viewController.tabBarItem respondsToSelector:@selector(badgeColor)]) {
                    viewController.tabBarItem.badgeColor = color;
                }
                viewController.tabBarItem.badgeValue = [NSString stringWithFormat:@"%@", badge];
            }
        }
    }
    
    if ([performAction isEqualToString:@"switchTo"]) {
        UIViewController *viewController = nil;
        NSNumber *tabIndex = actionParams[@"tabIndex"];
        if (tabIndex) {
            int i = (int)[tabIndex integerValue];
            
            if ([self.viewControllers count] > i) {
                viewController = [self.viewControllers objectAtIndex:i];
            }
        }
        NSString *contentId = actionParams[@"contentId"];
        NSString *contentType = actionParams[@"contentType"];
        if (contentId && contentType) {
            viewController = [[RCCManager sharedInstance] getControllerWithId:contentId componentType:contentType];
        }
        
        if (viewController) {
            [self setSelectedViewController:viewController];
        }
    }
    
    if ([performAction isEqualToString:@"setTabButton"]) {
        UIViewController *viewController = nil;
        NSNumber *tabIndex = actionParams[@"tabIndex"];
        if (tabIndex) {
            int i = (int)[tabIndex integerValue];
            
            if ([self.viewControllers count] > i) {
                viewController = [self.viewControllers objectAtIndex:i];
            }
        }
        NSString *contentId = actionParams[@"contentId"];
        NSString *contentType = actionParams[@"contentType"];
        if (contentId && contentType) {
            viewController = [[RCCManager sharedInstance] getControllerWithId:contentId componentType:contentType];
        }
        
        if (viewController) {
            UIImage *iconImage = nil;
            id icon = actionParams[@"icon"];
            if (icon && icon != (id)[NSNull null]) {
                iconImage = [RCTConvert UIImage:icon];
                iconImage = [[self image:iconImage withColor:self.tabBar.tintColor] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
                viewController.tabBarItem.image = iconImage;
            }
            
            UIImage *iconImageSelected = nil;
            id selectedIcon = actionParams[@"selectedIcon"];
            if (selectedIcon && selectedIcon != (id)[NSNull null]) {
                iconImageSelected = [RCTConvert UIImage:selectedIcon];
                viewController.tabBarItem.selectedImage = iconImageSelected;
            }
            
            id label = actionParams[@"label"];
            if (label && label != (id)[NSNull null]) {
                viewController.tabBarItem.title = label;
            }
        }
    }
    
    if ([performAction isEqualToString:@"setTabBarHidden"]) {
        BOOL hidden = [actionParams[@"hidden"] boolValue];
        self.tabBarHidden = hidden;
        
        CGRect nextFrame = self.tabBar.frame;
        nextFrame.origin.y = UIScreen.mainScreen.bounds.size.height - (hidden ? 0 : self.tabBar.frame.size.height);
        
        [UIView animateWithDuration: ([actionParams[@"animated"] boolValue] ? 0.45 : 0)
                              delay: 0
             usingSpringWithDamping: 0.75
              initialSpringVelocity: 0
                            options: (hidden ? UIViewAnimationOptionCurveEaseIn : UIViewAnimationOptionCurveEaseOut)
                         animations:^()
         {
             [self.tabBar setFrame:nextFrame];
         }
                         completion:^(BOOL finished)
         {
             if (completion != nil) {
                 completion();
             }
         }];
        return;
    } else if (completion != nil) {
        completion();
    }
}

+(void)sendScreenTabChangedEvent:(UIViewController*)viewController body:(NSDictionary*)body{
    [RCCTabBarController sendTabEvent:@"bottomTabSelected" controller:viewController body:body];
}

+(void)sendScreenTabPressedEvent:(UIViewController*)viewController body:(NSDictionary*)body{
    [RCCTabBarController sendTabEvent:@"bottomTabReselected" controller:viewController body:body];
}

+(void)sendTabEvent:(NSString *)event controller:(UIViewController*)viewController body:(NSDictionary*)body{
    if ([viewController.view isKindOfClass:[RCTRootView class]]){
        RCTRootView *rootView = (RCTRootView *)viewController.view;
        
        if (rootView.appProperties && rootView.appProperties[@"navigatorEventID"]) {
            NSString *navigatorID = rootView.appProperties[@"navigatorID"];
            NSString *screenInstanceID = rootView.appProperties[@"screenInstanceID"];
            
            
            NSMutableDictionary *screenDict = [NSMutableDictionary dictionaryWithDictionary:@
                                               {
                                                   @"id": event,
                                                   @"navigatorID": navigatorID,
                                                   @"screenInstanceID": screenInstanceID
                                               }];
            
            
            if (body) {
                [screenDict addEntriesFromDictionary:body];
            }
            
            [[[RCCManager sharedInstance] getBridge].eventDispatcher sendAppEventWithName:rootView.appProperties[@"navigatorEventID"] body:screenDict];
        }
    }
    
    if ([viewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController *navigationController = (UINavigationController*)viewController;
        UIViewController *topViewController = [navigationController topViewController];
        [RCCTabBarController sendTabEvent:event controller:topViewController body:body];
    }
}



@end
