/*
** AqDownloadsController
** 
** CHANGES:
** 0.2  (pozytron) Added "total", "downloadAtIndex", "totalBandwidth" and "totalBandwidthString"
** methods, along with some statusbar methods.
** 0.23 (pozytron) Added handling of image files
*/

#import "AcqActionsController.h"
#import "AcqPlayerController.h"
#import "AqApplicationController.h"
#import "AqCoreController.h"
#import "AqDownload.h"
#import "AqDownloadsController.h"
#import "AqDownloadsToolbarDelegate.h"
#import "AqiTunesController.h"
#import "AqMediaType.h"


@implementation AqDownloadsController

/* Initialization */
    
    + (AqDownloadsController*) instance; {
        static id instance = nil;
        if (!instance) instance = [[AqDownloadsController alloc] init];
        return instance;
    }

#pragma mark -
/* Events */

    - (id) representationForInfo: (id) theInfo; {
        return [theInfo objectAtIndex: 1];
    }
        
    - (void) addDownload: (id) theInfo; 
    {
        id obj, rep = [self representationForInfo: theInfo];
        if (!(obj = [self objectRepresenting: rep])) 
        {
            obj = [AqDownload downloadWithInfo: theInfo];
            [self addObject: obj representingObject: rep];

            [self updateCell: nil];
            [self statsUpdated];
        }
    }
    
    - (void) removeDownload: (id) theInfo; 
    {
        id rep = [self representationForInfo: theInfo];
        AqDownload* obj = [self objectRepresenting: rep];

        if (!obj) return;

        /* Download Actions */
        if ([obj isComplete]) {
            if (isMusic([obj pathExtension]))
                [AqiTunesController handleCompletedFile: [obj path]];
            else
                [AcqActionsController handleCompletedFile: [obj path]];
        }

        if ([defaults boolForKey: @"kAqAutoClearDownloads"]) {

            [self removeObject: obj];

        } else {
            
            //hasUnviewedCompleteFiles = YES;
            //[AqApplicationController updateDockIcon];
            
        }
        
        [self statsUpdated];
        [AqApplicationController updateDockIcon];
    }
    
    - (void) updateDownloadStats: (id) theInfo;
    {
        

        id rep = [self representationForInfo: theInfo];
        AqDownload* obj;
        
        if ((obj = [self objectRepresenting: rep])) {
            [obj updateStats: theInfo];
            [obj invalidateValues];
        }
    }


#pragma mark -
/* Actions */
    
    - (void) removeSelected: (id) sender; {
        [super removeSelected: sender];
        [AqApplicationController updateDockIcon];
    }

    - (BOOL) canOpenSelectedIniTunes;
    {
        id selectedDownloads = [self selectedObjects];
        int i, count = [selectedDownloads count];
        
        for (i=0; i<count; i++) {
            AqDownload* theDownload = [selectedDownloads objectAtIndex: i];
            if ([theDownload isComplete] && isMusic([theDownload pathExtension])) 
                return YES;
        }
        
        return NO;
    }

    - (BOOL) canPreviewSelected;
    {
        id selectedDownloads = [self selectedObjects];
        int i, count = [selectedDownloads count];
        
        for (i=0; i<count; i++) {
            AqDownload* theDownload = [selectedDownloads objectAtIndex: i];
            if (isMusic([theDownload pathExtension])) 
                return YES;
        }
        
        return NO;
    }

    - (BOOL) canRetrySelected;
    {
        id selectedDownloads = [self selectedObjects];
        int i, count = [selectedDownloads count];
        
        //if ([selectedDownloads count] > 1) return NO;
        
        for (i=0; i<count; i++) {
            AqDownload* theDownload = [selectedDownloads objectAtIndex: i];
            if ([theDownload canRetry]) 
                return YES;
        }
        
        return NO;
    }

    - (void) previewSelected: (id) sender; 
    {
        id e = [[self selectedObjects] objectEnumerator];
        AqDownload* d = [e nextObject];
        //NSLog(@"AqDownloadsController(previewSelected): %@",d);
        if (isMusic([d pathExtension])) {
            NSString* path = [[[self objectAtRow: [tableView selectedRow]] path] stringByExpandingTildeInPath];
            [AcqPlayerController play: path];
        }
    }

    - (void) retrySelected: (id) sender; 
    {
        id e = [[self selectedObjects] objectEnumerator];
        AqDownload* d;
        while ((d = [e nextObject])) {
            if ([d canRetry]) {
                [[AqCoreController instance] writeString: [NSString stringWithFormat: @"retryDownload|%@\n", d->localIdentifier]];
            }
        }
    }

    - (BOOL) canRequerySelected;
    {
        id selectedDownloads = [self selectedObjects];
        int i, count = [selectedDownloads count];
        
        if ([selectedDownloads count] > 1) return NO;
        
        for (i=0; i<count; i++) {
            AqDownload* theDownload = [selectedDownloads objectAtIndex: i];
            if (![theDownload isComplete])
                return YES;
        }
        
        return NO;
    }

    - (void) requerySelected: (id) sender; 
    {
        id e = [[self selectedObjects] objectEnumerator];
        AqDownload* d;
        while ((d = [e nextObject])) {
            if (![d isComplete]) {
                [[AqCoreController instance] writeString: [NSString stringWithFormat: @"requeryDownload|%@\n", d->localIdentifier]];
            }
        }
    }


#pragma mark -
/* Cell Update */
    
    #define ACTIVE NSLocalizedStringFromTable(@"%i active", @"DownloadsCell", @"")
    #define ACTIVEPENDING NSLocalizedStringFromTable(@"%i active, %i pending", @"DownloadsCell", @"")
    #define PENDING NSLocalizedStringFromTable(@"%i pending", @"DownloadsCell", @"")
    #define NONE NSLocalizedStringFromTable(@"no downloads", @"DownloadsCell", @"")

    - (void) updateCell: (id) sender; 
    {
        [self recalculateCounts];
        id string, image;
        NSString* imageName;
        
        if (active && !waiting) {
            string = [NSString stringWithFormat: ACTIVE, active];
            imageName = @"AcqDownloadGreen";

        } else if (active && waiting) {
            string = [NSString stringWithFormat: ACTIVEPENDING, active, waiting];
            imageName = @"AcqDownloadYellow";

        } else if (!active && waiting) {
            string = [NSString stringWithFormat: PENDING, waiting];
            imageName = @"AcqDownloadRed";

        } else {
            string = NONE;
            imageName = @"AcqDownloadGray";
            
        }
        if (complete) imageName = @"AcqCompletedLight";
        //NSLog(@"imageName:%@", imageName);
        image = [NSImage imageNamed:imageName];
        
        [[AqDrawerStatsTableView downloadsCell] setSecondary: string];
        [[AqDrawerStatsTableView downloadsCell] setPrimaryImage: image];
        [AqDrawerStatsTableView redrawDownloadsCell];
        
        //[[tableView window] setDocumentEdited: active];
    }

    - (void) recalculateCounts; 
    {
        /* compute the # of active, waiting, and complete */

        AqTransfer* o;
        id e = [objects objectEnumerator];
        
        complete = waiting = active = 0;
        
        while ((o = [e nextObject])) 
        {
            if ([o isActive]) {
                active++;
            } else if ([o isComplete]) {
                complete++;
            } else {
                waiting++;
            }
        }
        [[AqDownloadsToolbarDelegate instance] updateSweepItem];
        //NSLog(@"%i active, %i waiting", active, waiting);
    }


#pragma mark -
/* get... */

    - (int) active; {
        return active;
    }

    - (int) complete; {
        return complete;
    }
    
    - (int) waiting; {
        return waiting;
    }
    
    - (int) total; {
        return [objects count];
    }

#pragma mark -
/* utility methods */

    - (AqTransfer*) downloadAtIndex:(int)theIndex; 
    {
        AqTransfer* o = [objects objectAtIndex:theIndex];
        return o;
    }

    - (int) totalBandwidth; {
        int i, count = [objects count];
        float temp, bandwidth = 0;
        for (i=0; i<count; i++) {
            AqTransfer* o = [objects objectAtIndex: i];
            temp = [[o bandwidth] floatValue];
            bandwidth += temp;
            //NSLog(@"TotalBandwidth(%i): %f", i, temp);
        }
    
        //NSLog(@"TotalBandwidth: %i", bandwidth);
        return (int)bandwidth;
    }

    - (id) totalBandwidthString; {
        return [NSString stringWithFormat:@"%.1f kB/s", (float)[self totalBandwidth] / 1024];
    }

#pragma mark -
#define CANCEL NSLocalizedStringFromTable(@"Cancel Download", @"StatusBar", @"")
#define OPENFILE NSLocalizedStringFromTable(@"Open File", @"StatusBar", @"")
    
    - (NSMenu*) menuWithDownloads: (int)selectedItem; {
        int i, count = [objects count];
        
        NSMenu* m = [[[NSMenu alloc] initWithTitle: @""] autorelease];
        id selectedObj = [objects objectAtIndex: selectedItem];
        NSString* selectedItemName = [selectedObj name];
        NSMenuItem* nameItem = [[[NSMenuItem alloc] initWithTitle: selectedItemName action: @selector(showStatusDownload:) keyEquivalent: @""] autorelease];
        [nameItem setTarget: [AqDownloadsController class]];
        [nameItem setTag: selectedItem];
        [nameItem setImage: [NSImage imageNamed: ([selectedObj isActive]) ? @"AcqGreenLight" : @"AcqYellowLight"]];
        NSMenuItem* cancelItem = [[[NSMenuItem alloc] initWithTitle: CANCEL action: @selector(cancelStatusDownload:) keyEquivalent: @""] autorelease];
        [cancelItem setTarget: [AqDownloadsController class]];
        [cancelItem setImage: [NSImage imageNamed: @"AcqPlaceholder"]];
        [cancelItem setTag: selectedItem];
        NSMenuItem* openItem = [[[NSMenuItem alloc] initWithTitle: OPENFILE action: @selector(openStatusDownload:) keyEquivalent: @""] autorelease];
        [openItem setTarget: [AqDownloadsController class]];
        [openItem setImage: [NSImage imageNamed: @"AcqPlaceholder"]];
        [openItem setTag: selectedItem];
        
        [m addItem: nameItem];
        [m addItem: cancelItem];
        [m addItem: openItem];
        
        if (count > 1) {
            [m addItem: [NSMenuItem separatorItem]];
            for (i=0; i<count; i++) {
                if (i!=selectedItem) {
                    id itemObj = [objects objectAtIndex: i];
                    NSString* itemName = [itemObj name];
                    NSMenuItem* item = [[[NSMenuItem alloc] initWithTitle: itemName action: @selector(setDownloadForStatusFromMenu:) keyEquivalent: @""] autorelease];
                    [item setTarget: [AqDrawerController class]];
                    [item setImage: [NSImage imageNamed: ([itemObj isActive]) ? @"AcqGreenLight" : @"AcqRedLight"]];
                    if ([itemObj isWaiting]) [item setImage: [NSImage imageNamed: @"AcqYellowLight"]];
                    if ([itemObj isComplete]) [item setImage: [NSImage imageNamed: @"AcqCompletedLight"]];
                    [item setTag: i];
                    [m addItem: item];
                }
            }
        }
        return m;
    }
    
    + (void) cancelStatusDownload: (id) sender; {
        [[AqDrawerController instance] showStatusDownload: [sender tag]];
        [[AqDownloadsController instance] removeSelected: nil];
    }
    
    + (void) openStatusDownload: (id) sender; {
        [[AqDrawerController instance] showStatusDownload: [sender tag]];
        [[AqDownloadsController instance] openSelected: nil];
    }
    
    + (void) showStatusDownload: (id) sender; {
        [[AqDrawerController instance] showStatusDownload: [sender tag]];
    }

@end