//
//  FSFileListViewController.m
//  PDFReader
//
//  Created by Dong Li on 12-4-25.
//  Copyright (c) 2013年 ITX. All rights reserved.
//

#import "FSFileListViewController.h"
#import "PDFViewController.h"
#import "PhotoViewController.h"
#import "PSSortingViewController.h"
#import "IFWebViewController.h"
#import "IFNavigationController.h"
#import "FSFileNameViewController.h"
#import "FSTextViewController.h"
#import "FWUpdateViewController.h"
#import "FSFileInfoCell.h"
#import "FSFileItem.h"
#import "FSDirectoryMonitor.h"
#import "FSOperationManager.h"
#import <MobileCoreServices/MobileCoreServices.h>
#import <MediaPlayer/MediaPlayer.h>

#define kFileListRowHeight 54

#define reloadRowAtIndexPath(theIndexPath) { \
NSArray *indexPaths = [[NSArray alloc] initWithObjects:theIndexPath, nil]; \
[_tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade]; \
}

#define refresh() { [_fileItem clearSubitems]; [_tableView reloadData]; }

@interface FSFileListViewController (PrivateMethods)
- (void)deselect:(BOOL)animated;
- (void)onDone;
- (void)filterContentForSearchText:(NSString *)searchText scopeIndex:(NSInteger)scopeIndex;
- (void)sendEmailForFileItems:(NSArray *)fileItems;
@end

@implementation FSFileListViewController

@synthesize fileItem = _fileItem;

static FSFileListViewController *_currentFileListViewController = nil;
static UIDocumentInteractionController *_documentInteractionController = nil;

+ (FSFileListViewController *)currentFileListViewController {
    return _currentFileListViewController;
}

- (id)initWithFileItem:(FSFileItem *)fileItem {
    if (self = [super init]) {
        if (nil == fileItem) {
            return nil;
        }
        
        _fileItem = fileItem;
        _inboxDirectory = [_fileItem isInboxDirectory];
        _editItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(onEdit)];
        _doneItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(onDone)];
        
        UIBarButtonItem *flexibleItem, *tempItem;
        
        flexibleItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL];
        
        _normalToolbarItems = [[NSMutableArray alloc] initWithCapacity:9];
        
#define ADD_SYSTEM_ITEM(systemItem, method) {\
tempItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:systemItem target:self action:@selector(method)]; \
[_normalToolbarItems addObject:tempItem]; \
}
        
        ADD_SYSTEM_ITEM(UIBarButtonSystemItemAdd, onAdd);
        [_normalToolbarItems addObject:flexibleItem];
        
        ADD_SYSTEM_ITEM(UIBarButtonSystemItemRefresh, onRefresh);
        [_normalToolbarItems addObject:flexibleItem];
        
        tempItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"bar/sort.png"] style:UIBarButtonItemStylePlain target:self action:@selector(onSort)];
        [_normalToolbarItems addObject:tempItem];
//        [_normalToolbarItems addObject:flexibleItem];
//        [_normalToolbarItems addObject:_rotationItem];
        
#undef ADD_SYSTEM_ITEM
        
        _editingToolbarItems = [[NSMutableArray alloc] initWithCapacity:9];
        
#define ADD_EDITING_ITEM(title, method) {\
tempItem = [[UIBarButtonItem alloc] initWithTitle:title style:UIBarButtonItemStyleDone target:self action:@selector(method)]; \
[tempItem setWidth:56]; \
[_editingToolbarItems addObject:tempItem]; \
}
        
        [_editingToolbarItems addObject:flexibleItem];
        ADD_EDITING_ITEM(LS(@"COPY"), onCopyFiles);
        [_editingToolbarItems addObject:flexibleItem];
        ADD_EDITING_ITEM(LS(@"CUT"), onCutFiles);
        [_editingToolbarItems addObject:flexibleItem];
        ADD_EDITING_ITEM(LS(@"DELETE"), onDeleteFiles);
        [_editingToolbarItems addObject:flexibleItem];
        ADD_EDITING_ITEM(LS(@"ZIP"), onZipFiles);
        [_editingToolbarItems addObject:flexibleItem];
        ADD_EDITING_ITEM(LS(@"EMAIL"), onEmailFiles);
        [_editingToolbarItems addObject:flexibleItem];
        
#undef ADD_EDITING_ITEM
        
        [self setTitle:[_fileItem fileName]];
        [self setToolbarItems:_normalToolbarItems];
        [[self navigationItem] setRightBarButtonItem:_editItem];
        
        _selectedFiles = [[NSMutableArray alloc] init];
    }
    return self;
}

- (id)initWithPath:(NSString *)path {
    FSFileItem *fileItem = [[FSFileItem alloc] initWithPath:path];
    
    self = [self initWithFileItem:fileItem];
    return self;
}

- (id)initForSubDirectoryWithFileItem:(FSFileItem *)fileItem {
    if (self = [self initWithFileItem:fileItem]) {
    }
    return self;
}

- (void)loadView {
    _tableView = [[UITableView alloc] initWithFrame:CGRectPortraitScreen style:UITableViewStylePlain];
    [_tableView setDataSource:self];
    [_tableView setDelegate:self];
    [_tableView setRowHeight:kFileListRowHeight];
    [_tableView setAllowsSelectionDuringEditing:YES];
    
    _longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
    [_longPressGestureRecognizer setCancelsTouchesInView:NO];
    [_tableView addGestureRecognizer:_longPressGestureRecognizer];
    
    [self setView:_tableView];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [_tableView setContentOffset:_contentOffset];
    if (_selectedIndexPath) {
        [_tableView selectRowAtIndexPath:_selectedIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
    }
}

- (void)releaseSubviews {
    _contentOffset = [_tableView contentOffset];
    _tableView = nil;
    _fileSearchController = nil;
    _longPressGestureRecognizer = nil;
    _menuIndexPath = nil;
    _filteredSubFiles = nil;
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    
    if ([_documentInteractionController delegate] == self) {
        [_documentInteractionController setDelegate:nil];
        _documentInteractionController = nil;
    }
    
    if (self == _currentFileListViewController) {
        _currentFileListViewController = nil;
    }
    
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    _currentFileListViewController = self;
    
    if (_nextFileListViewController) {
        _nextFileListViewController = nil;
    }
}

- (void)viewDidAppear:(BOOL)animated {
    [self deselect:animated];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(menuControllerWillHideMenu) name:UIMenuControllerWillHideMenuNotification object:nil];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    
    if (_editing) {
        [self onDone];
    }
    
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIMenuControllerWillHideMenuNotification object:nil];
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (tableView == _tableView) {
        return [[_fileItem subitems] count];
    } else {
        return [_filteredSubFiles count];
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"FSFileInfoCell";
    FSFileInfoCell *cell = (FSFileInfoCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    
    if (nil == cell) {
        cell = [[FSFileInfoCell alloc] initWithReuseIdentifier:CellIdentifier];
    }
    
    if (tableView == _tableView) {
        [cell setFileItem:[[_fileItem subitems] objectAtIndex:[indexPath row]]];
    } else {
        [cell setFileItem:[_filteredSubFiles objectAtIndex:[indexPath row]]];
    }
    
    return cell;
}

#pragma mark - Table view delegate

- (void)updateEditingToolbarState {
    const NSInteger numberOfItems = [_editingToolbarItems count];
    BOOL enabled = ([_selectedFiles count] > 0);
    
    for (NSInteger i = 0; i < numberOfItems; ++ i) {
        UIBarButtonItem *barButtonItem = [_editingToolbarItems objectAtIndex:i];
        
        [barButtonItem setEnabled:enabled];
    }
    
    if (enabled) {
        [[_editingToolbarItems objectAtIndex:7] setEnabled:!_inboxDirectory];
    }
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    if (_longPressed) {
        _longPressed = NO;
        return;
    }
    
    FSFileItem *fileItem = nil;
    
    if (tableView == _tableView) {
        if (indexPath != _selectedIndexPath) {
            _selectedIndexPath = indexPath;
        }
        
        fileItem = [[_fileItem subitems] objectAtIndex:[indexPath row]];
        
        if (_editing) {
            [fileItem invertSelection];
            
            if ([fileItem isSelected]) {
                if (![_selectedFiles containsObject:fileItem]) {
                    [_selectedFiles addObject:fileItem];
                }
            } else {
                [_selectedFiles removeObject:fileItem];
            }
            [self updateEditingToolbarState];
            reloadRowAtIndexPath(indexPath);
            return;
        }
    } else {
        fileItem = [_filteredSubFiles objectAtIndex:[indexPath row]];
    }
    
    const FILE_CATEGORY fileCategory = [fileItem fileCategory];
    id viewController = nil;
    
    switch (fileCategory) {
        case FC_DIRECTORY: {
            viewController = [[FSFileListViewController alloc] initWithFileItem:fileItem];
            [[self navigationController] pushViewController:viewController animated:YES];
            _nextFileListViewController = viewController;
            return;
        }
        case FC_PLAIN_TEXT:
        case FC_SOURCE_CODE:
        {
            if ([fileItem fileSize] > SIZE_1_MB * 20) {
                UIAlert(LS(@"TEXT_FILE_SIZE_PROMPT"), nil);
                [tableView deselectRowAtIndexPath:indexPath animated:YES];
                _selectedIndexPath = nil;
                return;
            } else {
                viewController = [[FSTextViewController alloc] initWithPath:[fileItem path]];
            }
            break;
        }
        case FC_AUDIO:
        case FC_VIDEO:
        {
            NSURL *url = [[NSURL alloc] initFileURLWithPath:[fileItem path]];
            MPMoviePlayerViewController *moviePlayerViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
            
            [[self navigationController] presentMoviePlayerViewControllerAnimated:moviePlayerViewController];
            return;
        }
        case FC_PDF: {
            viewController = [[PDFViewController alloc] initWithFileItem:fileItem];
            break;
        }
        case FC_PHOTO: {
            viewController = [[PhotoViewController alloc] initWithFileItem:fileItem];
            break;
        }
        case FC_XML:
        case FC_OFFICE:
        case FC_RICH_TEXT:
        {
            viewController = [[IFWebViewController alloc] initWithFileItem:fileItem];
            break;
        }
        case FC_BIN: {
            [[NSNotificationCenter defaultCenter] postNotificationName:FWUpdateFilePathNotification object:nil userInfo:@{ @"url" : fileItem.path }];
            [self.navigationController dismissViewControllerAnimated:YES completion:NULL];
            return;
        }
        default: {
            [tableView deselectRowAtIndexPath:indexPath animated:YES];
            _selectedIndexPath = nil;
            return;
        }
    }
    
    if (viewController) {
        UINavigationController *navigationController = [[IFNavigationController alloc] initWithRootViewController:viewController];
        UINavigationBar *navigationBar = [navigationController navigationBar];
        UIToolbar *toolbar = [navigationController toolbar];
        
        [navigationController setToolbarHidden:NO];
        [toolbar setBarStyle:UIBarStyleBlack];
        [toolbar setTranslucent:YES];
        [navigationBar setBarStyle:UIBarStyleBlack];
        [navigationBar setTranslucent:YES];
        [[self navigationController] presentViewController:navigationController animated:YES completion:NULL];
    }
}

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
    return UITableViewCellEditingStyleNone;
}

#pragma mark - Action

- (void)deselect:(BOOL)animated {
    NSIndexPath *selectedIndexPath = [_tableView indexPathForSelectedRow];
    
    if (selectedIndexPath) {
        [_tableView deselectRowAtIndexPath:selectedIndexPath animated:animated];
    }
    _selectedIndexPath = nil;
}

- (void)filterContentForSearchText:(NSString *)searchText scopeIndex:(NSInteger)scopeIndex {
    if (nil == _filteredSubFiles) {
        _filteredSubFiles = [[NSMutableArray alloc] initWithCapacity:100];
    } else {
        [_filteredSubFiles removeAllObjects];
    }
    
    NSArray *subitems = [_fileItem subitems];
    
    for (FSFileItem *subInfo in subitems) {
        BOOL shouldCompare = NO;
        
        if (0 == scopeIndex) {
            shouldCompare = YES;
        } else {
            BOOL isDirectory = [subInfo isDirectory];
            
            shouldCompare = (isDirectory && 1 == scopeIndex) || (!isDirectory && 2 == scopeIndex);
        }
        if (shouldCompare) {
            const NSComparisonResult result = [[subInfo fileName] compare:searchText options:(NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
            
            if (NSOrderedSame == result) {
                [_filteredSubFiles addObject:subInfo];
            }
        }
    }
}

#pragma mark -

- (void)clearFileItemSelections {
    for (FSFileItem *fileItem in _selectedFiles) {
        [fileItem setSelected:NO];
        [fileItem setCut:NO];
    }
    [_selectedFiles removeAllObjects];
}

- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
    _editing = editing;
    
    if (_editing) {
        [self updateEditingToolbarState];
        [[self navigationItem] setRightBarButtonItem:_doneItem animated:animated];
        [self setToolbarItems:_editingToolbarItems animated:animated];
        [_tableView removeGestureRecognizer:_longPressGestureRecognizer];
    } else {
        [[self navigationItem] setRightBarButtonItem:_editItem animated:animated];
        [self setToolbarItems:_normalToolbarItems animated:animated];
        [_tableView addGestureRecognizer:_longPressGestureRecognizer];
    }
    [_tableView setEditing:_editing animated:animated];
}

- (void)onEdit {
    [self clearFileItemSelections];
    [self setEditing:YES animated:YES];
}

- (void)onDone {
    [self clearFileItemSelections];
    [self setEditing:NO animated:YES];
}

- (void)onAdd {
    UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:LS(@"NEW_FOLDER"), LS(@"NEW_TEXT_FILE"), nil];
    
    /*
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
        [sheet addButtonWithTitle:LS(@"PHOTO_LIBRARY")];
    }
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
        [sheet addButtonWithTitle:LS(@"CAMERA")];
    }
    */
    if ([[FSOperationManager sharedManager] canPaste] && !_inboxDirectory) {
        [sheet addButtonWithTitle:LS(@"PASTE")];
    }
    
    const NSUInteger cancelButtonIndex = [sheet numberOfButtons];
    
    [sheet addButtonWithTitle:LS(@"CANCEL")];
    [sheet setCancelButtonIndex:cancelButtonIndex];
    [sheet showInView:[[self navigationController] view]];
}

- (void)onRefresh {
    refresh();
}

- (void)onSort {
    PSSortingViewController *viewController = [[PSSortingViewController alloc] initForFileSystem];
    UINavigationController *navigationController = [[IFNavigationController alloc] initWithRootViewController:viewController];
    UINavigationBar *navigationBar = [navigationController navigationBar];
    UIToolbar *toolbar = [navigationController toolbar];
    
    [navigationController setToolbarHidden:YES];
    [toolbar setBarStyle:UIBarStyleDefault];
    [toolbar setTranslucent:NO];
    [navigationBar setBarStyle:UIBarStyleDefault];
    [navigationBar setTranslucent:NO];
    [[self navigationController] presentViewController:navigationController animated:YES completion:NULL];
}

- (void)runOperation:(SEL)aSelector withObject:(id)anObject {
    FSOperationManager *theManager = [FSOperationManager sharedManager];
    __weak __typeof(self) weakSelf = self;
    
    FSCompletionHandler completionHandler = ^(BOOL completed){
        __strong __typeof(weakSelf) strongSelf = weakSelf;
        
        if (strongSelf) {
            [strongSelf clearFileItemSelections];
            [strongSelf->_fileItem clearSubitems];
            [strongSelf->_tableView reloadData];
        }
    };
    
    [theManager performSelector:aSelector withObject:anObject withObject:completionHandler];
}

- (void)onCopyFiles {
    [self setEditing:NO animated:YES];
    [self runOperation:@selector(copyFileItems:completionBlock:) withObject:_selectedFiles];
}

- (void)onCutFiles {
    for (FSFileItem *fileItem in _selectedFiles) {
        [fileItem setCut:YES];
    }
    [self setEditing:NO animated:YES];
    [self runOperation:@selector(cutFileItems:completionBlock:) withObject:_selectedFiles];
}

- (void)onDeleteFiles {
    [self setEditing:NO animated:YES];
    [self runOperation:@selector(removeFileItems:completionBlock:) withObject:_selectedFiles];
}

- (void)onZipFiles {
    [self setEditing:NO animated:YES];
    [self runOperation:@selector(zipFileItems:completionBlock:) withObject:_selectedFiles];
}

- (void)onEmailFiles {
    [self setEditing:NO animated:YES];
    [self sendEmailForFileItems:_selectedFiles];
}

- (void)onRootDirectory {
    [[self navigationController] popToRootViewControllerAnimated:YES];
}

#pragma mark - UIImagePickerControllerDelegate

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    IFActivityView *activityView = [[IFActivityView alloc] initWithTitle:LS(@"COPYING")];
    
    [activityView setHidesCloseButton:YES];
    [activityView show];
    
    [self beginUpdate];
    
    [[[FSOperationManager sharedManager] operationQueue] addOperationWithBlock:^{
        @autoreleasepool {
            NSString *mediaType = [info valueForKey:UIImagePickerControllerMediaType];
            NSString *extension = [[info valueForKey:UIImagePickerControllerMediaURL] pathExtension];
            NSString *targetPath = nil;
            BOOL isMovie = NO;
            
            if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
                UIImage *originalImage = [info valueForKey:UIImagePickerControllerOriginalImage];
                NSData *data = nil;
                
                targetPath = FSPathForNewFileInDirectory([_fileItem path], @"Picture", extension);
                
                if (targetPath) {
                    if (NSOrderedSame == [extension caseInsensitiveCompare:@"png"]) {
                        data = UIImagePNGRepresentation(originalImage);
                    } else {
                        data = UIImageJPEGRepresentation(originalImage, 0.99);
                    }
                    
                    [data writeToFile:targetPath atomically:YES];
                }
            } else if ([mediaType isEqualToString:(NSString *)kUTTypeMovie]) {
                NSURL *mediaURL = [info valueForKey:UIImagePickerControllerMediaURL];
                
                targetPath = FSPathForNewFileInDirectory([_fileItem path], @"Movie", extension);
                
                if (mediaURL && targetPath) {
                    [theFileManager moveItemAtURL:mediaURL toURL:[NSURL fileURLWithPath:targetPath] error:NULL];
                }
                isMovie = YES;
            }
            dispatch_sync(dispatch_get_main_queue(), ^{
                [self endUpdate];
                if (isMovie || UIImagePickerControllerSourceTypeCamera == [picker sourceType]) {
                    [picker dismissViewControllerAnimated:YES completion:NULL];
                }
                [activityView done];
            });
        }
    }];
}

#pragma mark - UIMenuController

- (void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer {
    CGPoint location = [gestureRecognizer locationInView:_tableView];
    NSIndexPath *indexPath = [_tableView indexPathForRowAtPoint:location];
    
    if (indexPath) {
        _longPressed = YES;
        _menuIndexPath = indexPath;
    }
    
    UIMenuItem *tempItem;
    NSMutableArray *menuItems = [[NSMutableArray alloc] initWithCapacity:10];
    const BOOL isWritable = !_inboxDirectory;
    
#define ADD_MENU_ITEM(title, method) { \
tempItem = [[UIMenuItem alloc] initWithTitle:LS(title) action:@selector(method)]; \
[menuItems addObject:tempItem]; \
}
    
    if (indexPath) {
        ADD_MENU_ITEM(@"COPY", onCopy:);
        ADD_MENU_ITEM(@"CUT", onCut:);
    }
    if ([[FSOperationManager sharedManager] canPaste] && isWritable) {
        ADD_MENU_ITEM(@"PASTE", onPaste:);
    }
    if (indexPath) {
        ADD_MENU_ITEM(@"DELETE", onDelete:);
        
        if (isWritable) {
            ADD_MENU_ITEM(@"RENAME", onRename:);
            
            FSFileItem *fileItem = [[_fileItem subitems] objectAtIndex:[indexPath row]];
            
            if (FC_COMPRESSED == [fileItem fileCategory]) {
                ADD_MENU_ITEM(@"EXTRACT", onExtract:);
            } else {
                ADD_MENU_ITEM(@"ZIP", onZip:);
            }
        }
        ADD_MENU_ITEM(@"EMAIL", onEmail:);
        ADD_MENU_ITEM(@"OPEN_IN", openIn:);
    }
    
#undef ADD_MENU_ITEM
    
    if ([menuItems count] > 0) {
        UIMenuController *menuController = [UIMenuController sharedMenuController];
        const CGRect targetRect = { location, { 0, 0 } };
        
        [menuController setMenuItems:menuItems];
        [menuController setTargetRect:targetRect inView:_tableView];
        [self becomeFirstResponder];
        [menuController setMenuVisible:YES animated:YES];
    }
    
}

- (BOOL)canBecomeFirstResponder {
    return !_editing;
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    if (@selector(onPaste:) == action) {
        return [[FSOperationManager sharedManager] canPaste];
    }
    return (@selector(onCopy:) == action || @selector(onCut:) == action || @selector(onDelete:) == action || @selector(onRename:) == action || @selector(onZip:) == action || @selector(onExtract:) == action || @selector(onEmail:) == action || @selector(openIn:) == action);
}

- (void)menuControllerWillHideMenu {
    if (_menuIndexPath) {
        [_tableView deselectRowAtIndexPath:_menuIndexPath animated:YES];
        _menuIndexPath = nil;
    }
}

- (void)handleMenuActionWithSelector:(SEL)aSelector {
    if (_menuIndexPath) {
        FSFileItem *selectedItem = [[_fileItem subitems] objectAtIndex:[_menuIndexPath row]];
        NSArray *fileItems = [[NSArray alloc] initWithObjects:selectedItem, nil];
        
        [self runOperation:aSelector withObject:fileItems];
        
    }
}

- (void)onCopy:(id)sender {
    if (_menuIndexPath) {
        FSFileItem *selectedItem = [[_fileItem subitems] objectAtIndex:[_menuIndexPath row]];
        
        [selectedItem setSelected:YES];
        reloadRowAtIndexPath(_menuIndexPath);
    }
    [self handleMenuActionWithSelector:@selector(copyFileItems:completionBlock:)];
}

- (void)onCut:(id)sender {
    if (_menuIndexPath) {
        FSFileItem *selectedItem = [[_fileItem subitems] objectAtIndex:[_menuIndexPath row]];
        
        [selectedItem setSelected:YES];
        [selectedItem setCut:YES];
        reloadRowAtIndexPath(_menuIndexPath);
    }
    [self handleMenuActionWithSelector:@selector(cutFileItems:completionBlock:)];
}

- (void)onPaste:(id)sender {
    FSFileItem *fileItem = nil;
    
    if (_menuIndexPath) {
        fileItem = [[_fileItem subitems] objectAtIndex:[_menuIndexPath row]];
    } else {
        fileItem = _fileItem;
    }
    [self runOperation:@selector(pasteToFileItem:completionBlock:) withObject:fileItem];
}

- (void)onDelete:(id)sender {
    [self handleMenuActionWithSelector:@selector(removeFileItems:completionBlock:)];
}

- (void)renameWithTitle:(NSString *)title parentPath:(NSString *)directory originalFileName:(NSString *)name isDirectory:(BOOL)isDirectory {
    FSFileNameViewController *viewController = [[FSFileNameViewController alloc] initWithParentPath:directory];
    IFNavigationController *navigationController = [[IFNavigationController alloc] initWithRootViewController:viewController];
    UINavigationBar *navigationBar = [navigationController navigationBar];
    UIToolbar *toolbar = [navigationController toolbar];
    
    [navigationController setToolbarHidden:YES];
    [toolbar setBarStyle:UIBarStyleBlack];
    [toolbar setTranslucent:YES];
    [navigationBar setBarStyle:UIBarStyleBlack];
    [navigationBar setTranslucent:YES];
    [viewController setTitle:title];
    [viewController setDirectory:isDirectory];
    [viewController setOriginalFileName:name];
    [[self navigationController] presentViewController:navigationController animated:YES completion:NULL];
}

- (void)onRename:(id)sender {
    if (_menuIndexPath) {
        FSFileItem *fileItem = [[_fileItem subitems] objectAtIndex:[_menuIndexPath row]];
        
        [self renameWithTitle:LS(@"Rename") parentPath:[_fileItem path] originalFileName:[fileItem fileName] isDirectory:[fileItem isDirectory]];
    }
}

- (void)onZip:(id)sender {
    [self handleMenuActionWithSelector:@selector(zipFileItems:completionBlock:)];
}

- (void)onExtract:(id)sender {
    if (_menuIndexPath) {
        FSFileItem *fileItem = [[_fileItem subitems] objectAtIndex:[_menuIndexPath row]];
        
        [self runOperation:@selector(unzipFileItem:completionBlock:) withObject:fileItem];
    }
}

- (void)presentMailComposerWithPaths:(NSArray *)paths totalSize:(const UInt64)totalSize {
    if (totalSize > 15 * 1024 * 1024) {
        UIAlert(LS(@"EMAIL_SIZE_PROMPT"), nil);
    } else {
        MFMailComposeViewController *mailComposer = [[MFMailComposeViewController alloc] init];
        
        for (NSString *path in paths) {
            NSString *fileName = [path lastPathComponent];
            CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[fileName pathExtension], NULL);
            NSString *mimeType = (__bridge NSString *)UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType);
            NSData *data = [[NSData alloc] initWithContentsOfFile:path];
            
            [mailComposer addAttachmentData:data mimeType:mimeType fileName:fileName];
            CFRelease(UTI);
        }
        [mailComposer setMailComposeDelegate:self];
        
        [[self navigationController] presentViewController:mailComposer animated:YES completion:NULL];
    }
    refresh();
}

- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
    [controller dismissViewControllerAnimated:YES completion:NULL];
}

- (void)sendEmailForFileItems:(NSArray *)fileItems {
    if ([fileItems count] > 0 && [MFMailComposeViewController canSendMail]) {
        NSMutableArray *filePaths = [[NSMutableArray alloc] init];
        BOOL containsDirectory = NO;
        UInt64 totalSize = 0;
        
        for (FSFileItem *fileItem in fileItems) {
            if ([fileItem isDirectory]) {
                containsDirectory = YES;
                [filePaths removeAllObjects];
                break;
            }
            [filePaths addObject:[fileItem path]];
            totalSize += [fileItem fileSize];
        }
        
        if (containsDirectory) {
            if ([theFileManager fileExistsAtPath:FSTmpEmailDirectory]) {
                [theFileManager removeItemAtPath:FSTmpEmailDirectory error:NULL];
            }
            [theFileManager createDirectoryAtPath:FSTmpEmailDirectory withIntermediateDirectories:YES attributes:nil error:NULL];
            
            [[FSOperationManager sharedManager] zipFileItems:fileItems toPath:FSTmpEmailDirectory completionBlock:^(BOOL completed){
                if (completed) {
                    NSArray *zipFileNames = [theFileManager contentsOfDirectoryAtPath:FSTmpEmailDirectory error:NULL];
                    NSMutableArray *zipPaths = [[NSMutableArray alloc] init];
                    
                    for (NSString *fileName in zipFileNames) {
                        if ([fileName hasSuffix:@".zip"]) {
                            [zipPaths addObject:[FSTmpEmailDirectory stringByAppendingPathComponent:fileName]];
                            break;
                        }
                    }   //  end for
                    
                    UInt64 fileSize = 0;
                    
                    if ([zipPaths count] > 0) {
                        NSDictionary *attributes = [theFileManager attributesOfItemAtPath:[zipPaths objectAtIndex:0] error:NULL];
                        fileSize = [[attributes valueForKey:NSFileSize] unsignedLongLongValue];
                    }
                    [self presentMailComposerWithPaths:zipPaths totalSize:fileSize];
                    
                }   // end if (completed)
                
            }]; //  end block
            
        } else {
            
            [self presentMailComposerWithPaths:filePaths totalSize:totalSize];
            
        }   //  end if (containsDirectory)
        
    }
}

- (void)onEmail:(id)sender {
    if (_menuIndexPath) {
        FSFileItem *fileItem = [[_fileItem subitems] objectAtIndex:[_menuIndexPath row]];
        
        [self sendEmailForFileItems:[NSArray arrayWithObject:fileItem]];
    }
}

- (void)openIn:(id)sender {
    if (_menuIndexPath) {
        FSFileItem *fileItem = [[_fileItem subitems] objectAtIndex:[_menuIndexPath row]];
        NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:[fileItem path]];
        UIView *anchorView = [[self navigationController] view];
        
        if (nil == _documentInteractionController) {
            _documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
        }
        [_documentInteractionController setDelegate:self];
        [_documentInteractionController presentOpenInMenuFromRect:[anchorView bounds] inView:anchorView animated:YES];
        
    }
}

#pragma mark -

- (void)presentImagePickerForType:(UIImagePickerControllerSourceType)type {
    UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
    
    [imagePicker setDelegate:self];
    [imagePicker setSourceType:type];
    [imagePicker setMediaTypes:[UIImagePickerController availableMediaTypesForSourceType:type]];
    
    [[self navigationController] presentViewController:imagePicker animated:YES completion:NULL];
}

#pragma mark UIActionSheetDelegate

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    if ([actionSheet cancelButtonIndex] != buttonIndex) {
        if (1 >= buttonIndex) {
            [self renameWithTitle:[actionSheet buttonTitleAtIndex:buttonIndex] parentPath:[_fileItem path] originalFileName:nil isDirectory:!buttonIndex];
        } else {
            NSInteger nextIndex = 2;
            
            if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
                if (nextIndex ++ == buttonIndex) {
                    [self presentImagePickerForType:UIImagePickerControllerSourceTypePhotoLibrary];
                }
            }
            if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
                if (nextIndex ++ == buttonIndex) {
                    [self presentImagePickerForType:UIImagePickerControllerSourceTypeCamera];
                }
            }
            
            FSOperationManager *operationManager = [FSOperationManager sharedManager];
            
            if ([operationManager canPaste]) {
                if (nextIndex ++ == buttonIndex) {
                    [operationManager pasteToFileItem:_fileItem completionBlock:^(BOOL completed){
                        refresh();
                    }];
                }
            }
        }
    }
}

#pragma mark - UIDocumentInteractionControllerDelegate

- (void)documentInteractionControllerDidDismissOpenInMenu: (UIDocumentInteractionController *)controller {
    if (controller == _documentInteractionController) {
        [_documentInteractionController setDelegate:nil];
        _documentInteractionController = nil;
    }
}
- (void)documentInteractionController:(UIDocumentInteractionController *)controller didEndSendingToApplication:(NSString *)application {
    if (controller == _documentInteractionController) {
        [_documentInteractionController setDelegate:nil];
        _documentInteractionController = nil;
    }
}

#pragma mark -

- (void)selectIndexPath:(NSIndexPath *)indexPath {
    [_tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionMiddle];
    
    if (indexPath != _selectedIndexPath) {
        _selectedIndexPath = indexPath;
    }
}

- (void)beginUpdate {
    [_fileItem clearSubitems];
}

- (void)endUpdate {
    [_tableView reloadData];
}

- (void)refresh {
    refresh();
}

- (void)handleOpenPath:(NSString *)path {
    [_fileItem loadAttributesIfNeeded];
    
    NSString *currentPath = [_fileItem path];
    const NSUInteger currentLength = [currentPath length];
    
    if ([path length] > currentLength) {
        NSString *relativePath = [path substringFromIndex:(currentLength + 1)];
        NSArray *subitems = [_fileItem subitems];
        const NSUInteger numberOfItems = [subitems count];
        
        for (NSUInteger i = 0; i < numberOfItems; ++ i) {
            FSFileItem *fileItem = [subitems objectAtIndex:i];
            
            if ([relativePath hasPrefix:[fileItem fileName]]) {
                NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
                
                if ([fileItem isDirectory]) {
                    FSFileListViewController *viewController = [[FSFileListViewController alloc] initWithFileItem:fileItem];
                    
                    [[self navigationController] pushViewController:viewController animated:NO];
                    [viewController handleOpenPath:path];
                } else {
                    [fileItem loadAttributesIfNeeded];
                    [self tableView:_tableView didSelectRowAtIndexPath:indexPath];
                }
                [self performSelector:@selector(selectIndexPath:) withObject:indexPath afterDelay:0];
                break;
            }
        }
    }
}

@end
