/*
** AqTransferController
** 
** CHANGES:
** 0.21 (pozytron) Fixed context menu displaying "Acquisition" playlist.
** 0.23 (pozytron) "Open With" menu revamped.
*/

#import "AcqActionsController.h"
#import "AqApplicationController.h"
#import "AqBrowseHostToolbarView.h"
#import "AqDownloadsController.h"
#import "AqiTunesController.h"
#import "AqMediaType.h"
#import "AqTransferController.h"
#import "AqTransferController(Table).h"
#import "DWVersionChecker.h"
#import "NSDateExtensions.h"
#import "NSMenuExtensions.h"


@implementation AqTransferController

#pragma mark -
/* Initialization */
    
    + (id) instance; {
        static id instance = nil;
        if (!instance) instance = [[AqTransferController alloc] init];
        return instance;
    }

    - (id) init; {
        self = [super init];
        [self performSelector: @selector(updateCell:) withObject: nil afterDelay: 0];
        [self initTable];
        return self;
    }


#pragma mark -
/* Contextual Menu */

    #define OPEN NSLocalizedStringFromTable(@"Open", @"TransferContextMenu", @"")
    #define OPENWITH NSLocalizedStringFromTable(@"Open With", @"TransferContextMenu", @"")
    #define REVEAL NSLocalizedStringFromTable(@"Reveal in Finder", @"TransferContextMenu", @"")
    #define ITUNESLIBRARY NSLocalizedStringFromTable(@"Add to iTunes Library", @"TransferContextMenu", @"")
    #define ITUNESPLAYLIST NSLocalizedStringFromTable(@"Add to iTunes \"%@\" Playlist", @"TransferContextMenu", @"")
    #define RETRY NSLocalizedStringFromTable(@"Retry", @"TransferContextMenu", @"")
    #define REQUERY NSLocalizedStringFromTable(@"Find More Sources", @"TransferContextMenu", @"")
    #define CLEARCOMPLETE NSLocalizedStringFromTable(@"Clear All Completed", @"TransferContextMenu", @"")
    #define CLEAROFFLINE NSLocalizedStringFromTable(@"Clear All Offline", @"TransferContextMenu", @"")
    #define REMOVE NSLocalizedStringFromTable(@"Remove", @"TransferContextMenu", @"")
    #define REMOVEALL NSLocalizedStringFromTable(@"Remove All", @"TransferContextMenu", @"")
   
    #define DEFAULT NSLocalizedStringFromTable(@"Default", @"QueryResultsContextMenu", @"String in Open With menus.")
        
    #define ITUNESDEFAULTPLAYLIST [NSString stringWithFormat: ITUNESPLAYLIST, [defaults stringForKey: @"kAqPlaylistName"]]
    
    + (NSImage*) iconForApplication: (id) theApp; {
        id theImg = [[NSWorkspace sharedWorkspace] iconForFile: [[NSWorkspace sharedWorkspace] fullPathForApplication: theApp]];
        if (theImg) {
            [theImg setScalesWhenResized: YES];
            [theImg setSize: NSMakeSize(16.0,16.0)];
        }
        return theImg;
    }
    
    - (void) cacheMenuIcons; {
        if (!qtItem)
            qtItem = [AqTransferController iconForApplication:@"QuickTime Player.app"];
        
        if (!itItem)
            itItem = [AqTransferController iconForApplication:@"iTunes.app"];
        
        if (!vlcItem)
            vlcItem = [AqTransferController iconForApplication:@"VLC.app"];
        
        if (!mpItem)
            mpItem = [AqTransferController iconForApplication:@"MPlayer OS X 2.app"];
        
        if (!prItem)
            prItem = [AqTransferController iconForApplication:@"Preview.app"];
        
        if (!bbItem)
            bbItem = [AqTransferController iconForApplication:@"BBEdit Lite 6.1 for OS X"];
        
        if (!gcItem)
            gcItem = [AqTransferController iconForApplication:@"GraphicConverter.app"];
        
        if (!teItem)
            teItem = [AqTransferController iconForApplication:@"TextEdit.app"];
        
        cached = YES;
    }
    
    + (NSMenu*) videoMenuWithTarget: (id) target; {
        NSMenu *m;
        NSMenuItem *i;
        
        if (![self instance]->cached) [[self instance] cacheMenuIcons];

        m  = [[[NSMenu alloc] initWithTitle: @"nil"] retain];
        
        i = [[[NSMenuItem alloc] initWithTitle: DEFAULT action: @selector(openSelected:) keyEquivalent: @""] autorelease];
        [i setTag: kAqVideo];
        [i setTarget: target];
        [m addItem: i];
        
        [m addItem: [NSMenuItem separatorItem]];

        i = [[[NSMenuItem alloc] initWithTitle: @"QuickTime Player" action: @selector(openSelectedWithApp:) keyEquivalent: @""] autorelease];
        [i setTarget: target];
//        [i setImage: [self instance]->qtItem];
        [i setTag: kAqVideo];
        [m addItem: i];

        i = [[[NSMenuItem alloc] initWithTitle: @"MPlayer OS X 2" action: @selector(openSelectedWithApp:) keyEquivalent: @""] autorelease];
        [i setTarget: target];
//        [i setImage: [self instance]->mpItem];
        [i setTag: kAqVideo];
        [m addItem: i];

        i = [[[NSMenuItem alloc] initWithTitle: @"VLC" action: @selector(openSelectedWithApp:) keyEquivalent: @""] autorelease];
        [i setTarget: target];
//        [i setImage: [self instance]->vlcItem];
        [i setTag: kAqVideo];
        [m addItem: i];
        
        return m;
    }
    
    + (NSMenu*) musicMenuWithTarget: (id) target; {
        NSMenu *m;
        NSMenuItem *i;
        
        if (![self instance]->cached) [[self instance] cacheMenuIcons];

        m  = [[[NSMenu alloc] initWithTitle: @"nil"] retain];
        
        i = [[[NSMenuItem alloc] initWithTitle: DEFAULT action: @selector(openSelected:) keyEquivalent: @""] autorelease];
        [i setTag: kAqMusic];
        [i setTarget: target];
        [m addItem: i];
        
        [m addItem: [NSMenuItem separatorItem]];

        i = [[[NSMenuItem alloc] initWithTitle: @"iTunes" action: @selector(openSelectedWithApp:) keyEquivalent: @""] autorelease];
        [i setTarget: target];
//        [i setImage: [self instance]->itItem];
        [i setTag: kAqMusic];
        [m addItem: i];

        i = [[[NSMenuItem alloc] initWithTitle: @"QuickTime Player" action: @selector(openSelectedWithApp:) keyEquivalent: @""] autorelease];
        [i setTarget: target];
//        [i setImage: [self instance]->qtItem];
        [i setTag: kAqMusic];
        [m addItem: i];

        i = [[[NSMenuItem alloc] initWithTitle: @"MPlayer OS X 2" action: @selector(openSelectedWithApp:) keyEquivalent: @""] autorelease];
        [i setTarget: target];
//        [i setImage: [self instance]->mpItem];
        [i setTag: kAqMusic];
        [m addItem: i];

        i = [[[NSMenuItem alloc] initWithTitle: @"VLC" action: @selector(openSelectedWithApp:) keyEquivalent: @""] autorelease];
        [i setTarget: target];
//        [i setImage: [self instance]->vlcItem];
        [i setTag: kAqMusic];
        [m addItem: i];
        
        return m;
    }
    
    + (NSMenu*) imageMenuWithTarget: (id) target; {
        NSMenu *m;
        NSMenuItem *i;
        
        if (![self instance]->cached) [[self instance] cacheMenuIcons];
        
        m  = [[[NSMenu alloc] initWithTitle: @"nil"] retain];
        
        i = [[[NSMenuItem alloc] initWithTitle: DEFAULT action: @selector(openSelected:) keyEquivalent: @""] autorelease];
        [i setTag: kAqImage];
        [i setTarget: target];
        [m addItem: i];
        
        [m addItem: [NSMenuItem separatorItem]];

        i = [[[NSMenuItem alloc] initWithTitle: @"Preview" action: @selector(openSelectedWithApp:) keyEquivalent: @""] autorelease];
        [i setTarget: target];
//        [i setImage: [self instance]->prItem];
        [i setTag: kAqImage];
        [m addItem: i];

        i = [[[NSMenuItem alloc] initWithTitle: @"GraphicConverter" action: @selector(openSelectedWithApp:) keyEquivalent: @""] autorelease];
        [i setTarget: target];
//        [i setImage: [self instance]->gcItem];
        [i setTag: kAqImage];
        [m addItem: i];
                    
        return m;
    }
    
    + (NSMenu*) textMenuWithTarget: (id) target; {
        NSMenu *m;
        NSMenuItem *i;
        
        if (![self instance]->cached) [[self instance] cacheMenuIcons];
        m  = [[[NSMenu alloc] initWithTitle: @"nil"] retain];
        
        i = [[[NSMenuItem alloc] initWithTitle: DEFAULT action: @selector(openSelected:) keyEquivalent: @""] autorelease];
        [i setTag: kAqDocument];
        [i setTarget: target];
        [m addItem: i];
        
        [m addItem: [NSMenuItem separatorItem]];

        i = [[[NSMenuItem alloc] initWithTitle: @"TextEdit" action: @selector(openSelectedWithApp:) keyEquivalent: @""] autorelease];
        [i setTarget: target];
//        [i setImage: [[self instance]->teItem copy]];
        [i setTag: kAqDocument];
        [m addItem: i];

        i = [[[NSMenuItem alloc] initWithTitle: @"BBEdit Lite 6.1 for OS X" action: @selector(openSelectedWithApp:) keyEquivalent: @""] autorelease];
        [i setTarget: target];
//        [i setImage: [self instance]->bbItem];
        [i setTag: kAqDocument];
        [m addItem: i];
                    
        return m;
    }

    - (id) menuForEvent: (NSEvent*) theEvent; 
    {
        NSMenu *m, *m1;
        NSMenuItem *i;
        BOOL openWithUnhandled = YES;

        m  = [[[NSMenu alloc] initWithTitle: @"nil"] autorelease];
        m1 = [[[NSMenu alloc] initWithTitle: @"nil"] autorelease];
    
        int row = [tableView rowAtPoint: [theEvent locationInView: tableView]];
        if (row >= 0 && ![tableView isRowSelected: row])
            [tableView selectRow: row byExtendingSelection: NO];
        
        BOOL atLeastOneRowSelected = ([tableView selectedRow] >= 0);
        BOOL exactlyOneRowSelected = ([tableView numberOfSelectedRows] == 1);

        [[tableView window] makeFirstResponder: tableView];
            
        if (exactlyOneRowSelected)
        {
            i = [[[NSMenuItem alloc] initWithTitle: OPEN action: @selector(openSelected:) keyEquivalent: @""] autorelease];
            [i setTarget: self];
            [m addItem: i];
            
            switch(AqMediaTypeForExtension([[self objectAtRow: [tableView selectedRow]] pathExtension])) {
                case kAqMusic:
                    m1 = [AqTransferController musicMenuWithTarget: self];
                    openWithUnhandled = NO;
                    break;
                    
                case kAqDocument:
                    m1 = [AqTransferController textMenuWithTarget: self];
                    openWithUnhandled = NO;
                    break;
                    
                case kAqVideo:
                    m1 = [AqTransferController videoMenuWithTarget: self];
                    openWithUnhandled = NO;
                    break;
                    
                case kAqImage:
                    m1 = [AqTransferController imageMenuWithTarget: self];
                    openWithUnhandled = NO;
                    break;
                
                default:
                    openWithUnhandled = YES;
                    break;
            }
            
            if (!openWithUnhandled) {
                i = [[[NSMenuItem alloc] initWithTitle: OPENWITH action: nil keyEquivalent: @""] autorelease];
                [i setSubmenu: m1];
                [m addItem: i];
            }

            i = [[[NSMenuItem alloc] initWithTitle: REVEAL action: @selector(revealSelected:) keyEquivalent: @""] autorelease];
            [i setTarget: self];
            [m addItem: i];
        }

        if ([self isKindOfClass: [AqDownloadsController class]] && (atLeastOneRowSelected && [(AqDownloadsController*)self canOpenSelectedIniTunes])) 
        {
            [m addSeparator];

            i = [[[NSMenuItem alloc] initWithTitle: ITUNESLIBRARY action: @selector(addSongToLibrary:) keyEquivalent: @""] autorelease];
            [i setTarget: self];
            [m addItem: i];

            i = [[[NSMenuItem alloc] initWithTitle: ITUNESDEFAULTPLAYLIST action: @selector(addSongToPlaylist:) keyEquivalent: @""] autorelease];
            [i setTarget: self];
            [m addItem: i];
        }

        if ([self isKindOfClass: [AqDownloadsController class]]) 
        {
            BOOL canRetry = (atLeastOneRowSelected && [(AqDownloadsController*)self canRetrySelected]);
            BOOL canRequery = (atLeastOneRowSelected && [(AqDownloadsController*)self canRequerySelected]);

            if (canRetry || canRequery)
                [m addSeparator];

            if (canRetry) {
                i = [[[NSMenuItem alloc] initWithTitle: RETRY action: @selector(retrySelected:) keyEquivalent: @""] autorelease];
                [i setTarget: self];
                [m addItem: i];
            }

            if (canRequery) {
                i = [[[NSMenuItem alloc] initWithTitle: REQUERY action: @selector(requerySelected:) keyEquivalent: @""] autorelease];
                [i setTarget: self];
                [m addItem: i];
            }
        }

        [m addSeparator];
        i = [[[NSMenuItem alloc] initWithTitle: CLEARCOMPLETE action: @selector(clearAllComplete:) keyEquivalent: @""] autorelease];
        [i setTarget: self];
        [m addItem: i];

        if ([self isKindOfClass: [AqDownloadsController class]]) 
        {
            i = [[[NSMenuItem alloc] initWithTitle: CLEAROFFLINE action: @selector(clearAllOffline:) keyEquivalent: @""] autorelease];
            [i setTarget: self];
            [m addItem: i];
        }

        [m addSeparator];
    
        if (atLeastOneRowSelected)
        {
            i = [[[NSMenuItem alloc] initWithTitle: REMOVE action: @selector(removeSelected:) keyEquivalent: @""] autorelease];
            [i setTarget: self];
            [m addItem: i];
        }

        i = [[[NSMenuItem alloc] initWithTitle: REMOVEALL action: @selector(removeAll:) keyEquivalent: @""] autorelease];
        [i setTarget: self];
        [m addItem: i];
        
        /* browse host */
            
            [AqBrowseHostToolbarView addBrowseableHostsToMenu: m];

        /* fix */
        
            if ([[m itemAtIndex: 0] isSeparatorItem]) {
                [m removeItemAtIndex: 0];
            }

        return m;
    }
    

#pragma mark -
/* Keys */

    - (void) enterKeyPressed; {
        [self openSelected: nil];
    }

    - (void) doubleAction: (id) sender; {
        if ([sender clickedRow] >= 0) {
            [self openSelected: self];
        }
    }


#pragma mark -
/* Actions */
    
    - (void) openSelectedWithApp: (id) sender; 
    {
        if ([tableView selectedRow] >= (int)[objects count]) return;
        
        id targetApplication = [sender title];

        id path = [[self objectAtRow: [tableView selectedRow]] path];
        if ([[NSFileManager defaultManager] fileExistsAtPath: path]) {
            [[NSWorkspace sharedWorkspace] openFile: path withApplication: targetApplication];
        }
    }
    
    - (void) openSelected: (id) sender; 
    {
        if ([tableView selectedRow] >= (int)[objects count]) return;

        id path = [[self objectAtRow: [tableView selectedRow]] path];
        [AcqActionsController openFile: path];
    }
    
    - (void) addSongToLibrary: (id) sender;
    {
        AqTransfer* o;
        id e = [[self selectedObjects] objectEnumerator];
        while ((o = [e nextObject])) {
            if ([o isComplete] && isMusic([o pathExtension])) {
                [AqiTunesController addSongToLibrary: [o path]];
            }
        }
    }

    - (void) addSongToPlaylist: (id) sender;
    {
        AqTransfer* o;
        id e = [[self selectedObjects] objectEnumerator];
        while ((o = [e nextObject])) {
            if ([o isComplete] && isMusic([o pathExtension])) {
                [AqiTunesController addSongToPlaylist: [o path]];
            }
        }
    }

    - (void) clearAllComplete: (id) sender;
    {
        [self saveSelectedObjects];
        
        AqTransfer* o;
        id e = [objects objectEnumerator];
        while ((o = [e nextObject])) {
            if ([o isComplete]) {
                [self removeObject: o];
            }
        }

        [self restoreSelectedObjects];
        [tableView noteNumberOfRowsChanged];
        
        [self updateCell: nil];
        [AqApplicationController updateDockIcon];
    }

    - (void) clearAllOffline: (id) sender;
    {
        [self saveSelectedObjects];
        
        AqTransfer* o;
        id e = [objects objectEnumerator];
        while ((o = [e nextObject])) {
            if ([o isOffline]) {
                [o remove];
                [self removeObject: o];
            }
        }

        [self restoreSelectedObjects];
        [tableView noteNumberOfRowsChanged];
        
        [self updateCell: nil];
    }

    - (void) revealSelected: (id) sender; {
        if ([tableView selectedRow] < (int)[objects count]) {
            NSString* path = [[[self objectAtRow: [tableView selectedRow]] path] stringByExpandingTildeInPath];
            if ([[NSFileManager defaultManager] fileExistsAtPath: path]) {
                [[NSWorkspace sharedWorkspace] selectFile: path inFileViewerRootedAtPath: @""];
            }
        }
    }
    

#pragma mark -

    - (BOOL) hasOffline; {
        return NO;
    }
    
    - (BOOL) hasComplete; {
        return NO;
    }

@end