// Copyright 2019 Google LLC.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

#include "tools/skottie_ios_app/SkiaContext.h"
#include "tools/skottie_ios_app/SkottieViewController.h"

#include "include/core/SkTypes.h"

#import <UIKit/UIKit.h>

#include <cstdlib>

@interface AppViewController : UIViewController
    @property (strong) SkiaContext* skiaContext;
    @property (strong) UIStackView* stackView;
@end

@implementation AppViewController

- (void)loadView {
    [self setView:[[UIView alloc] init]];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    if (![self skiaContext]) {
        #if defined(SK_GANESH) && defined(SK_METAL)
        [self setSkiaContext:MakeSkiaMetalContext()];
        #elif defined(SK_GANESH) && defined(SK_GL)
        [self setSkiaContext:MakeSkiaGLContext()];
        #else
        [self setSkiaContext:MakeSkiaUIContext()];
        #endif
        if (![self skiaContext]) {
            NSLog(@"abort: failed to make skia context.");
            std::abort();
        }
    }
    CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;

    UIStackView* stack = [[UIStackView alloc] init];
    [stack setAxis:UILayoutConstraintAxisVertical];
    [stack setDistribution:UIStackViewDistributionEqualSpacing];

    NSBundle* mainBundle = [NSBundle mainBundle];
    NSArray<NSString*>* paths = [mainBundle pathsForResourcesOfType:@"json"
                                            inDirectory:@"data"];
    constexpr CGFloat kSpacing = 2;
    CGFloat totalHeight = kSpacing;
    for (NSUInteger i = 0; i < [paths count]; ++i) {
        NSString* path = [paths objectAtIndex:i];
        NSData* content = [NSData dataWithContentsOfFile:path];
        if (!content) {
            NSLog(@"'%@' not found", path);
            continue;
        }
        SkottieViewController* controller = [[SkottieViewController alloc] init];
        if (![controller loadAnimation:content]) {
            continue;
        }
        CGSize animSize = [controller size];
        CGFloat height = animSize.width ? (screenWidth * animSize.height / animSize.width) : 0;
        CGRect frame = {{0, 0}, {screenWidth, height}};
        UIView* skiaView = [[self skiaContext] makeViewWithController:controller withFrame:frame];
        [[[skiaView heightAnchor] constraintEqualToConstant:height] setActive:true];
        [[[skiaView widthAnchor] constraintEqualToConstant:screenWidth] setActive:true];
        [skiaView setNeedsDisplay];
        [stack addArrangedSubview:skiaView];
        totalHeight += height + kSpacing;
    }
    [stack setFrame:{{0, 0}, {screenWidth, totalHeight}}];
    [stack setNeedsDisplay];

    CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
    CGSize mainScreenSize = [[UIScreen mainScreen] bounds].size;
    CGRect scrollViewBounds = {{0, statusBarHeight},
                               {mainScreenSize.width, mainScreenSize.height - statusBarHeight}};
    UIScrollView* scrollView = [[UIScrollView alloc] initWithFrame:scrollViewBounds];
    [scrollView setContentSize:[stack frame].size];
    [scrollView addSubview:stack];
    [scrollView setBackgroundColor:[UIColor blackColor]];
    [scrollView setNeedsDisplay];

    [self setStackView:stack];

    UIView* mainView = [self view];
    [mainView setBounds:{{0, 0}, mainScreenSize}];
    [mainView setBackgroundColor:[UIColor whiteColor]];
    [mainView addSubview:scrollView];
    [mainView setNeedsDisplay];

    UITapGestureRecognizer* tapGestureRecognizer = [[UITapGestureRecognizer alloc] init];
    [tapGestureRecognizer addTarget:self action:@selector(handleTap:)];
    [mainView addGestureRecognizer:tapGestureRecognizer];
}

- (void)handleTap:(UIGestureRecognizer*)sender {
    if ([sender state] != UIGestureRecognizerStateEnded) {
        return;
    }
    NSArray<UIView*>* subviews = [[self stackView] subviews];
    for (NSUInteger i = 0; i < [subviews count]; ++i) {
        UIView* uIView = [subviews objectAtIndex:i];
        if (SkiaViewController* controller = [[self skiaContext] getViewController:uIView]) {
            [controller togglePaused];
            [uIView setNeedsDisplay];
        }
    }
}
@end

@interface AppDelegate : UIResponder <UIApplicationDelegate>
    @property (strong, nonatomic) UIWindow* window;
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication*)app didFinishLaunchingWithOptions:(NSDictionary*)ops {
    [self setWindow:[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]];
    [[self window] setRootViewController:[[AppViewController alloc] init]];
    [[self window] makeKeyAndVisible];
    return YES;
}
@end

int main(int argc, char* argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}
