// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "MainViewController.h"

#import "AppDelegate.h"
#import "DualFlutterViewController.h"
#import "FullScreenViewController.h"
#import "HybridViewController.h"
#import "NativeViewController.h"

@interface MainViewController ()

@property (weak, nonatomic) UIButton* flutterViewWarmButton;

@end


@implementation MainViewController {
  UIStackView *_stackView;
}

- (void)viewDidLoad {
  [super viewDidLoad];

  [self.view setFrame:self.view.window.bounds];
  self.title = @"Flutter iOS Demos Home";
  self.view.backgroundColor = UIColor.whiteColor;

  _stackView = [[UIStackView alloc] initWithFrame:self.view.frame];
  _stackView.axis = UILayoutConstraintAxisVertical;
  _stackView.distribution = UIStackViewDistributionEqualSpacing;
  _stackView.alignment = UIStackViewAlignmentCenter;
  _stackView.autoresizingMask =
      UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  _stackView.layoutMargins = UIEdgeInsetsMake(0, 0, 50, 0);
  _stackView.layoutMarginsRelativeArrangement = YES;
  [self.view addSubview:_stackView];

  [self addButton:@"Native iOS View" action:@selector(showNative)];
  [self addButton:@"Full Screen (Cold)" action:@selector(showFullScreenCold)];
  [self addButton:@"Full Screen (Warm)" action:@selector(showFullScreenWarm)];
  self.flutterViewWarmButton = [self addButton:@"Flutter View (Warm)" action:@selector(showFlutterViewWarm)];
  [self addButton:@"Hybrid View (Warm)" action:@selector(showHybridView)];
  [self addButton:@"Dual Flutter View (Cold)" action:@selector(showDualView)];
}

- (FlutterEngine *)engine {
  return [(AppDelegate *)[[UIApplication sharedApplication] delegate] engine];
}

- (FlutterBasicMessageChannel*)reloadMessageChannel {
  return [(AppDelegate *)[[UIApplication sharedApplication] delegate] reloadMessageChannel];
}

- (void)showDualView {
  DualFlutterViewController *dualViewController =
      [[DualFlutterViewController alloc] init];
  [self.navigationController pushViewController:dualViewController
                                       animated:YES];
}

- (void)showHybridView {
  HybridViewController *hybridViewController =
      [[HybridViewController alloc] init];
  [self.navigationController pushViewController:hybridViewController
                                       animated:YES];
}
- (void)showNative {
  NativeViewController *nativeViewController =
      [[NativeViewController alloc] init];
  [self.navigationController pushViewController:nativeViewController
                                       animated:YES];
}

- (void)showFullScreenCold {
  FullScreenViewController *flutterViewController =
      [[FullScreenViewController alloc] init];
  [flutterViewController setInitialRoute:@"full"];
  [[self reloadMessageChannel] sendMessage:@"full"];
  [self.navigationController
      pushViewController:flutterViewController
                animated:NO]; // Animating this is janky because of
                              // transitions with header on the native side.
                              // It's especially bad with a cold engine.
}

- (void)showFullScreenWarm {
  [[self engine].navigationChannel invokeMethod:@"setInitialRoute"
                                      arguments:@"full"];
  [[self reloadMessageChannel] sendMessage:@"full"];

  FullScreenViewController *flutterViewController =
      [[FullScreenViewController alloc] initWithEngine:[self engine]
                                               nibName:nil
                                                bundle:nil];
  [self.navigationController
      pushViewController:flutterViewController
                animated:NO]; // Animating this is problematic.
}

- (void)showFlutterViewWarm {
  self.flutterViewWarmButton.backgroundColor = UIColor.redColor;
  FlutterEngine *engine = [self engine];
  FlutterBasicMessageChannel* messageChannel = [self reloadMessageChannel];
  NSAssert(engine != nil, @"Engine is not nil.");
  NSAssert(engine.navigationChannel != nil, @"Engine.navigationChannel is not nil.");
  NSAssert(messageChannel != nil, @"messageChannel is not nil.");

  [engine.navigationChannel invokeMethod:@"setInitialRoute"
                                      arguments:@"/"];
  [messageChannel sendMessage:@"/"];


  FlutterViewController *flutterViewController =
      [[FlutterViewController alloc] initWithEngine:[self engine]
                                            nibName:nil
                                             bundle:nil];
  flutterViewController.view.accessibilityLabel = @"flutter view";
  NSAssert(self.navigationController != nil, @"self.navigationController is not nil.");
  [self.navigationController pushViewController:flutterViewController
                                       animated:NO];

  if (self.navigationController.topViewController != flutterViewController) {
    // For debugging:
    // Some unknown issue happened caused `flutterViewController` not being pushed.
    // We try to push an basic UIViewController to see if it would work.
    UIViewController *viewController = [[UIViewController alloc] init];
    viewController.view.backgroundColor = UIColor.blueColor;
    [self.navigationController pushViewController:viewController
                                         animated:NO];
    NSAssert(self.navigationController.topViewController == viewController, @"self.navigationController.topViewController should be the basic view controller");
  }
}

- (UIButton *)addButton:(NSString *)title action:(SEL)action {
  UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
  [button setTitle:title forState:UIControlStateNormal];
  [button addTarget:self
                action:action
      forControlEvents:UIControlEventTouchUpInside];
  [_stackView addArrangedSubview:button];
  return button;
}

@end
