//
//  CommitListViewController.m
//  FLEXample
//
//  Created by Tanner on 3/11/20.
//  Copyright © 2020 Flipboard. All rights reserved.
//

#import "CommitListViewController.h"
#import "FLEXample-Swift.h"
#import "Person.h"
#import <FLEX.h>

@interface CommitListViewController ()
@property (nonatomic) FLEXMutableListSection<Commit *> *commits;
@property (nonatomic, readonly) NSMutableDictionary<NSString *, UIImage *> *avatars;
@end

@interface UIAlertController (Private)
@property (nonatomic) UIViewController *contentViewController;
@end

@interface ContentViewController : UIViewController
+ (instancetype)customView:(UIView *)view;
@end

@implementation ContentViewController

+ (instancetype)customView:(UIView *)view {
    ContentViewController *vc = [self new];
    vc.view = view;
    return vc;
}

@end

@implementation CommitListViewController

- (id)init {
    // Default style is grouped
    return [self initWithStyle:UITableViewStylePlain];
}

- (void)showCustomView {
    UIAlertController *alert = [FLEXAlert makeAlert:^(FLEXAlert *make) {
        make.title(@"Custom View").button(@"Dismiss").cancelStyle();
    }];
    
    // I like to use this to easily display and interact with custom views I'm working on
    alert.contentViewController = [ContentViewController customView:[UIView new]];
    [self presentViewController:alert animated:YES completion:nil];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    _avatars = [NSMutableDictionary new];
    
    self.title = @"FLEX Commit History";
    self.showsSearchBar = YES;
    self.navigationItem.rightBarButtonItem = [UIBarButtonItem
        flex_itemWithTitle:@"FLEX" target:FLEXManager.sharedManager action:@selector(toggleExplorer)
    ];
    self.navigationItem.rightBarButtonItem.accessibilityIdentifier = @"toggle-explorer";
    
    self.navigationItem.leftBarButtonItem = [UIBarButtonItem
        flex_itemWithTitle:@"Test" target:self action:@selector(showCustomView)
    ];
    
    // Load and process commits
    NSString *commitsURL = @"https://api.github.com/repos/Flipboard/FLEX/commits";
    [self startDataTask:commitsURL completion:^(NSData *data, NSInteger statusCode, NSError *error) {
        if (statusCode == 200) {
            self.commits.list = [Commit commitsFrom:data];
            [self fadeInNewRows];
        } else {
            [FLEXAlert showAlert:@"Error"
                message:error.localizedDescription ?: @(statusCode).stringValue
                from:self
            ];
        }
    }];
    
    FLEXManager *flex = FLEXManager.sharedManager;
    
    // Register 't' for testing: quickly present an object explorer for debugging
    [flex registerSimulatorShortcutWithKey:@"t" modifiers:0 action:^{
        [flex showExplorer];
        [flex presentTool:^UINavigationController *{
            return [FLEXNavigationController withRootViewController:[FLEXObjectExplorerFactory
                explorerViewControllerForObject:Person.bob
            ]];
        } completion:nil];
    } description:@"Present an object explorer for debugging"];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    [self disableToolbar];
}

- (NSArray<FLEXTableViewSection *> *)makeSections {
    _commits = [FLEXMutableListSection list:@[]
        cellConfiguration:^(__kindof UITableViewCell *cell, Commit *commit, NSInteger row) {
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
            cell.textLabel.text = commit.firstLine;
            cell.detailTextLabel.text = commit.secondLine;
            cell.detailTextLabel.lineBreakMode = NSLineBreakByTruncatingTail;
//            cell.textLabel.numberOfLines = 2;
//            cell.detailTextLabel.numberOfLines = 3;
        
            UIImage *avi = self.avatars[commit.committer.login];
            if (avi) {
                cell.imageView.image = avi;
            } else {
                cell.tag = commit.identifier;
                [self loadImage:commit.committer.avatarUrl completion:^(UIImage *image) {
                    self.avatars[commit.committer.login] = image;
                    if (cell.tag == commit.identifier) {
                        cell.imageView.image = image;
                    } else {
                        [self.tableView reloadRowsAtIndexPaths:@[
                            [NSIndexPath indexPathForRow:row inSection:0]
                        ] withRowAnimation:UITableViewRowAnimationAutomatic];
                    }
                }];
            }
        } filterMatcher:^BOOL(NSString *filterText, Commit *commit) {
            return [commit matchesWithQuery:filterText];
        }
    ];
    
    self.commits.selectionHandler = ^(__kindof UIViewController *host, Commit *commit) {
        [host.navigationController pushViewController:[
            FLEXObjectExplorerFactory explorerViewControllerForObject:commit
        ] animated:YES];
    };
    
    return @[self.commits];
}

// Empty sections are removed by default and we always want this one section
- (NSArray<FLEXTableViewSection *> *)nonemptySections {
    return @[_commits];
}

- (void)fadeInNewRows {
    NSIndexSet *sections = [NSIndexSet indexSetWithIndex:0];
    [self.tableView reloadSections:sections withRowAnimation:UITableViewRowAnimationAutomatic];
}

- (void)loadImage:(NSString *)imageURL completion:(void(^)(UIImage *image))callback {
    [self startDataTask:imageURL completion:^(NSData *data, NSInteger statusCode, NSError *error) {
        if (statusCode == 200) {
            callback([UIImage imageWithData:data]);
        }
    }];
}

- (void)startDataTask:(NSString *)urlString completion:(void (^)(NSData *data, NSInteger statusCode, NSError *error))completionHandler {
//    return;
    NSURL *url = [NSURL URLWithString:urlString];
    [[NSURLSession.sharedSession dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSInteger code = [(NSHTTPURLResponse *)response statusCode];
            
            completionHandler(data, code, error);
        });
    }] resume];
}

@end
