/*
** AqDrawerController
** 
** CHANGES:
** 0.1  (pozytron) Changed some references from "Drawer" to "Sidebar," and added methods
** to collapse the sidebar.
** 0.2  (pozytron) Disabled de-rounding of corners (for Pantheresque look). Also added
** statusbar methods. (Somewhat) repaired the search cancel/refresh buttons (mouseOver events
** are still broken).
** 0.23 (pozytron) Added "statusDownloadPercent" method
*/

#import "AqContentViewController.h"
#import "AqDownloadsController.h"
#import "AqDrawerController.h"
#import "AqNetworkController.h"
#import "AqQueryCell.h"
#import "AqUploadsController.h"
#import "AqURLHandler.h"
#import "DWUtil.h"
#import "NSEventExtensions.h"
#import "NSObjectExtensions.h"
#import "NSTableViewExtensions.h"
#import "NSUserDefaultsExtensions.h"


#define kAqQueryCancelDelay 150


@implementation AqDrawerController

/* Initialization */

    static id instance = nil;
    
    + (AqDrawerController*) instance; {
        return instance;
    }
    
    - (void) awakeFromNib; 
    {
         //[window setBottomCornerRounded:NO];
        /* alloc */
        
            instance = self;
            qc = [AqQueryController instance];
            [splitView setDelegate: instance];

            trackingTags = [[NSMutableArray alloc] init];
            mouseOverRow = -1;
                
        /* queryView */
        
            id cell = [[[AqQueryCell alloc] init] autorelease];
            [[[queryView tableColumns] objectAtIndex: 0] setDataCell: cell];
    
        /* disable view/bounds did change notifications whereever possible */
            
            [statsView setPostsFrameChangedNotifications: NO];
            [[statsView enclosingScrollView] setPostsFrameChangedNotifications: NO];
            [[[statsView enclosingScrollView] verticalScroller] setPostsFrameChangedNotifications: NO];
            [[[statsView enclosingScrollView] horizontalScroller] setPostsFrameChangedNotifications: NO];
            [[[queryView enclosingScrollView] horizontalScroller] setPostsFrameChangedNotifications: NO];

            [statsView setPostsBoundsChangedNotifications: NO];
            [[statsView enclosingScrollView] setPostsBoundsChangedNotifications: NO];
            [[[statsView enclosingScrollView] verticalScroller] setPostsBoundsChangedNotifications: NO];
            [[[statsView enclosingScrollView] horizontalScroller] setPostsBoundsChangedNotifications: NO];
            [[[queryView enclosingScrollView] horizontalScroller] setPostsBoundsChangedNotifications: NO];
            
        /* events */
            
            [self listenForNotification: NSTableViewSelectionDidChangeNotification selector: @selector(queryViewSelectionDidChange:) object: queryView];
            [self listenForNotification: DWTableViewFirstResponderNotification selector: @selector(queryViewFirstResponder:) object: queryView];
            
        /* statsView */
        
            [self listenForNotification: DWTableViewFirstResponderNotification selector: @selector(statsViewSelectionDidChange:) object: statsView];
            [self listenForNotification: NSTableViewSelectionDidChangeNotification selector: @selector(statsViewSelectionDidChange:) object: statsView];
            //[self listenForNotification: DWTableViewFirstResponderNotification selector: @selector(statsViewFirstResponder:) object: statsView];
        
        /* animation timer */
            
            [self repeatingTimerWithTimeInterval: 0.07 selector: @selector(animationTimer:)];
        
        /* tracking rect timer */
        
            [self repeatingTimerWithTimeInterval: 1.0 selector: @selector(resetTrackingRects:)];
    }
    
    - (void) openDrawer: (id) sender; {
        [[AqContentViewController instance] showAnonymousView: defaultView inBox: contentView];
        [[AqDownloadsController instance] updateCell: nil];
        [[AqUploadsController instance] updateCell: nil];
        [AqQC loadDefaults];
        [queryView scrollRowToVisible: 0];
        [window makeKeyAndOrderFront: self];
    }


#pragma mark -
/* Defaults */

    - (void) applicationDidFinishLaunching; {
        //NSSize size = [defaults sizeForKey: @"kAqDrawerControllerSizeKey"];
        //if (size.width && size.height) {
            // [drawer setContentSize: size];
        //}
        [self openDrawer: nil];
    }
    
    - (void) applicationWillTerminate; {
        [super applicationWillTerminate];
        // [defaults setSize: [drawer contentSize] forKey: @"kAqDrawerControllerSizeKey"];
    }


#pragma mark -
/* Actions */

    - (void) toggleSidebar; {
        if (collapsed) [self uncollapseSidebar];
        else [self collapseSidebar];
    }

    - (IBAction) deleteSelectedQueries: (id) sender; {
        [self shouldDeleteSelection];
    }
    
    - (IBAction) deleteAllQueries: (id) sender; {
        [queryView selectAll: self];
        [self shouldDeleteSelection];
    }
    

#pragma mark -
/* Events */
    
    - (void) shouldDeleteSelection; 
    {
        id n, e = [queryView selectedRowEnumerator];
        id rows = [[[NSMutableArray alloc] init] autorelease];
        int i, index = 0;

        while ((n = [e nextObject])) {
            [rows addObject: n];
        }
        
        /* delete from top down to prevent issues */
            
        for (i=[rows count]-1; i>=0; i--) {
            index = [[rows objectAtIndex: i] intValue];
            [qc removeQueryAtIndex: index];
        }

        [queryView deselectAll: self];
        [queryView noteNumberOfRowsChanged];
    }
    
    - (void) animationTimer: (id) sender; 
    {
        int i, count = [qc count];

        for (i=0; i<count; i++) 
        {
            BOOL shouldRedraw = NO;
            BOOL isActive = [qc isActiveAtIndex: i];
            AqQueryCell* cell = [qc cellAtIndex: i];

            /* is the cell active (rotating animation) */
            
                if (isActive) {
                    cell->rotation = (int)(cell->rotation + 5.0f) % 360;
                    shouldRedraw = YES;
                }

            /* bg fade */

                if (cell->bgOpacity > cell->bgOpacityTarget) {
                    cell->bgOpacity -= 0.3f;
                    shouldRedraw = YES;
                }

                if (cell->bgOpacity < cell->bgOpacityTarget) {
                    cell->bgOpacity += 0.1f;
                    shouldRedraw = YES;
                }

            /* control opacity */

                if (cell->controlOpacity > cell->controlOpacityTarget) {
                    cell->controlOpacity -= 0.3f;
                    shouldRedraw = YES;
                }

                if (cell->controlOpacity < cell->controlOpacityTarget) {
                    cell->controlOpacity += 0.3f;
                    shouldRedraw = YES;
                }            
            
            /* draw cell if needed */
            
                if (shouldRedraw) 
                {
                    NSRect redrawRect = AqQueryCellTrackingRectInFrame([queryView frameOfCellAtColumn: 0 row: i]);
                    
                    /* not sure why the following correction is necessary */

                    redrawRect.origin.x -= 1.0f;
                    redrawRect.origin.y -= 1.0f;
                    
                    [queryView setNeedsDisplayInRect: redrawRect];
                }
        }
    }

    - (void) resetAllFileCounts; {
        int i, count = [queryView numberOfRows];
        for (i=0; i<count; i++) {
            [[[qc queryAtIndex: i] dataSource] updateCell: nil];
        }
    }
    
    

#pragma mark -
/* Search */

    - (void) trigger: (id) sender; {
        [self performSelector: @selector(_trigger:) withObject: sender afterDelay: 0];
    }
    
    - (void) _trigger: (id) sender; 
    {
        id query = [[sender stringValue] retain];
        
        if ([query isEqual: @""]) return;

        [sender setStringValue: @""];

        if ([query hasPrefix: @"acquisition:"] || [query hasPrefix: @"magnet:"] || [query hasPrefix: @"acql:"]) {
            [AqURLHandler handleURLStringAndDisplay: query];
        } else {
            [qc addQuery: [[[AqQuery alloc] initWithString: query] autorelease]];
            [queryView noteNumberOfRowsChanged];
    
            int index = [qc indexOfQuery: query];
            [queryView selectRow: index byExtendingSelection: NO];
            [queryView scrollRowToVisible: index];
    
            [self performSelector: @selector(stopQuery:) withObject: [qc queryAtIndex: index] afterDelay: kAqQueryCancelDelay];
    
            [[sender window] makeFirstResponder: sender];
        }

        [query release];
    }
    
    - (void) searchFromMenu: (id) sender; {
        [self textQuery: [sender title]];
        //[[sender window] makeFirstResponder: sender];
    }
    
    - (void) textQuery: (NSString*) theQuery; {
        if ([theQuery isEqual: @""]) return;
        
        [qc addQuery: [[[AqQuery alloc] initWithString: theQuery] autorelease]];
        [queryView noteNumberOfRowsChanged];
        
        int index = [qc indexOfQuery: theQuery];
        [queryView selectRow: index byExtendingSelection: NO];
        [queryView scrollRowToVisible: index];
        
        [self performSelector: @selector(stopQuery:) withObject: [qc queryAtIndex: index] afterDelay: kAqQueryCancelDelay];
    }

#pragma mark -
/* Tracking Rects (for Start/Stop buttons in queryView) */

    /*
        resetTrackingRects is called on a timer every second and does the actual work of resetting the tracking rectangles.  It is not called directly, since it adds unnecessary overhead during live resizing.
    */
    
    - (void) resetTrackingRects: (id) sender;
    {
        

        /* remove existing tracking rects */
    
            int i, count = [trackingTags count];
            
            for (i=count-1; i>=0; i--) {
                NSTrackingRectTag trackingTag = [[trackingTags objectAtIndex: i] intValue];
                [queryView removeTrackingRect: trackingTag];
                [trackingTags removeObjectAtIndex: i];
            }
        
        /* reconstruct the tracking rects */
        
            count = [queryView numberOfRows];
            
            for (i=0; i<count; i++) 
            {
                AqQueryCell* cell = [qc cellAtIndex: i];
                if (!cell->isBrowseHostCell /* && !cell->isActive */)
                {
                    //NSRect trackingRect = NSIntersectionRect([[queryView enclosingScrollView] documentVisibleRect], AqQueryCellTrackingRectInFrame([queryView frameOfCellAtColumn: 0 row: i]));
                    NSRect trackingRect = AqQueryCellTrackingRectInFrame([queryView frameOfCellAtColumn: 0 row: i]);
                    NSTrackingRectTag trackingTag = [queryView addTrackingRect: trackingRect owner: self userData: nil assumeInside: NO];
                    [trackingTags addObject: NINT(trackingTag)];
                }
            }
    }


#pragma mark -
/* Mouse Events */

    - (void) mouseEntered: (NSEvent*) event; 
    {
        //Bypass the broken crap for now.
        return;
        
        NSPoint locationInWindow = [event locationInWindow];
        NSLog(@"locationInWindow: (%f,%f)", locationInWindow.x, locationInWindow.y);
        NSPoint locationInView = [queryView convertPoint: locationInWindow fromView: [window contentView]];
        
        /* if mouseExited wasn't called for some reason */
        
            if (mouseOverRow >= 0) {
                AqQueryCell* cell = [qc cellAtIndex: mouseOverRow];
                cell->bgOpacityTarget = 0;
                cell->mouseOver = NO;
                [queryView setNeedsDisplayInRect: [queryView rectOfRow: mouseOverRow]];
            }
        
        locationInView.y += 3;	/* ???? */
        mouseOverRow = [queryView rowAtPoint: locationInView];
    
        if (mouseOverRow >= 0) {
            AqQueryCell* cell = [qc cellAtIndex: mouseOverRow];
            cell->bgOpacity = 0.8;
            cell->bgOpacityTarget = 0.8;
            cell->mouseOver = YES;
        }
        
        [queryView setNeedsDisplayInRect: [queryView rectOfRow: mouseOverRow]];
    }
    
    - (void) mouseExited: (NSEvent*) event; 
    {
        //Bypass the broken crap for now.
        return;
        
        int oldRow = mouseOverRow;

        if (mouseOverRow >= 0) {
            AqQueryCell* cell = [qc cellAtIndex: mouseOverRow];
            cell->bgOpacityTarget = 0;
            cell->mouseOver = NO;
        }

        mouseOverRow = -1;
        [queryView setNeedsDisplayInRect: [queryView rectOfRow: oldRow]];
    }
    
    /* queryView events */
    
    - (BOOL) doMouseUp: (NSEvent*) event; 
    {
        NSPoint locInView = [event locationInView: queryView];
        int row = [queryView rowAtPoint: locInView];

        //NSLog(@"doMouseUp: %@, %i", event, row);
        
        /* double-click */
        
        if ( row >= 0 && (unsigned)row < [qc count] && [event clickCount] == 2) {
            [self toggleSelected: nil];
            return NO;
        }
        
        /* normal flow */
        
        if (mouseOverRow >= 0) {
            AqQueryCell* cell = [qc cellAtIndex: mouseOverRow];
            cell->bgOpacityTarget = 0;
            cell->mouseOver = NO;
            cell->mouseDown = NO;
        }
        
        if (row >= 0 && row == mouseOverRow && locInView.x <= 20) {
            [self setActive: ![qc isActiveAtIndex: row] atIndex: row];
        }
    
        [queryView setNeedsDisplay: YES];

        return NO;
    }
    
    - (BOOL) doMouseDown: (NSEvent*) event; 
    {
        NSPoint locInView = [event locationInView: queryView];
        int row = [queryView rowAtPoint: locInView];
        AqQueryCell* cell;
        
        //NSLog(@"doMouseDown: %@, %i", event, row);
        
        if (row >= 0 && locInView.x <= 20)
        {
            cell = [qc cellAtIndex: row];
            cell->bgOpacity = 1.0;
            cell->bgOpacityTarget = 1.0;
            cell->mouseDown = YES;
            
            mouseOverRow = row;
            
            [queryView setNeedsDisplayInRect: [queryView rectOfRow: row]];
            return YES;
        }
        
        return NO;
    }


#pragma mark -
/* Selection Change Events */

    #define setWindowTitle(A) [window setTitle: [NSString stringWithFormat: @"AcqLite - %@", A]]

    - (void) queryViewSelectionDidChange: (id) sender; 
    {
        int selectedRow = [queryView selectedRow];
        [statsView deselectAll: self];

        if (selectedRow >= 0) {

            setWindowTitle([qc stringAtIndex: selectedRow]);

            [toolbarDelegate enableQueryViewElements];
            [toolbarDelegate disableTransferViewElements];

            [[AqContentViewController instance] showQueryViewAtIndex: selectedRow inBox: contentView];

        } else {

            [window setTitle: @"AcqLite"];
            
            [toolbarDelegate disableQueryViewElements];
            [toolbarDelegate disableTransferViewElements];
            
            [[AqContentViewController instance] showAnonymousView: defaultView inBox: contentView];

        }
    }
    
    - (void) queryViewFirstResponder: (id) sender; {
        [statsView deselectAll: self];
        [self performSelector: @selector(queryViewSelectionDidChange:) withObject: nil afterDelay: 0];
    }

    - (void) statsViewSelectionDidChange: (id) sender; 
    {
        if ([[statsView window] firstResponder] != statsView) return;
        
        switch ([statsView selectedRow]) {
            case 0:
                setWindowTitle(NSLocalizedStringFromTable(@"Network", @"Drawer", @"Drawer cell"));
                [toolbarDelegate disableQueryViewElements];
                [toolbarDelegate disableTransferViewElements];
                [[AqContentViewController instance] showNetworkViewInBox: contentView];
                break;
            case 1:
                setWindowTitle(NSLocalizedStringFromTable(@"Downloads", @"Drawer", @"Drawer cell"));
                [toolbarDelegate disableQueryViewElements];
                [toolbarDelegate enableTransferViewElementsWithTarget: [AqDownloadsController instance]];
                [[AqContentViewController instance] showDownloadsViewInBox: contentView];
                break;
            case 2:
                setWindowTitle(NSLocalizedStringFromTable(@"Uploads", @"Drawer", @"Drawer cell"));
                [toolbarDelegate disableQueryViewElements];
                [toolbarDelegate enableTransferViewElementsWithTarget: [AqUploadsController instance]];
                [[AqContentViewController instance] showUploadsViewInBox: contentView];
                break;
        }
    }


#pragma mark -
/* IB Events */

    #define drawerWindow (NSWindow*)[[drawer contentView] nextResponder]

    - (IBAction) mainWindow: (id) sender; {
        [window makeKeyAndOrderFront: self];
    }
    
    - (IBAction) command1: (id) sender; 
    {
        if ([[window toolbar] customizationPaletteIsRunning]) return;
        
        int nSelected = [queryView numberOfSelectedRows];

        if ([queryView numberOfRows] > 0 && !nSelected) 
            [queryView selectRow: 0 byExtendingSelection: NO];
        
        if (1) {
        //if ([window firstResponder] != queryView) {
        
            /* make first responder */

          [window makeFirstResponder: queryView];
          //  [self queryViewSelectionDidChange: self];

        } else {

            if (nSelected == 1) {

                /* rotate through selections */
                
                int currentRow = [queryView selectedRow];
                int i = currentRow;
                
                while (true) 
                {
                    i = (i+1) % [queryView numberOfRows];
                    if (i == currentRow) break;
                    
                    if ([[qc queryAtIndex: i] count]) {
                        [queryView selectRow: i byExtendingSelection: NO];
                        break;
                    }
                }
            
            } else {
                    
                /* select first row of current selection */
                [queryView selectRow: [queryView firstSelectedRow] byExtendingSelection: NO];
            
            }

        }
        
        if ([queryView selectedRow] >= 0) [queryView scrollRowToVisible: [queryView selectedRow]];
        [self mainWindow: self];
    }

    - (IBAction) command2: (id) sender; {
        if ([[window toolbar] customizationPaletteIsRunning]) return;
        [window makeFirstResponder: statsView];
        [statsView selectRow: 0 byExtendingSelection: NO];
        [self mainWindow: self];
    }

    - (IBAction) command3: (id) sender; {
        if ([[window toolbar] customizationPaletteIsRunning]) return;
        [window makeFirstResponder: statsView];
        [statsView selectRow: 1 byExtendingSelection: NO];
        [self mainWindow: self];
    }

    - (IBAction) command4: (id) sender; {
        if ([[window toolbar] customizationPaletteIsRunning]) return;
        [window makeFirstResponder: statsView];
        [statsView selectRow: 2 byExtendingSelection: NO];
        [self mainWindow: self];
    }


#pragma mark -
/* Activity */

    - (IBAction) startSelected: (id) sender; {
        id n, e = [queryView selectedRowEnumerator];
        while ((n = [e nextObject])) {
            int index = [n intValue];
            if (![qc isActiveAtIndex: index] && [qc userCanStartQueryAtIndex: index])
                [self setActive: YES atIndex: index];
        }
    }
    
    - (IBAction) stopSelected: (id) sender; {
        id n, e = [queryView selectedRowEnumerator];
        while ((n = [e nextObject])) {
            int index = [n intValue];
            if ([qc isActiveAtIndex: index] && [qc userCanStopQueryAtIndex: index])
                [self setActive: NO atIndex: index];
        }
    }

    - (IBAction) toggleSelected: (id) sender; {
        id n, e = [queryView selectedRowEnumerator];
        while ((n = [e nextObject])) {
            int index = [n intValue];
            if ([qc isActiveAtIndex: index] && [qc userCanStopQueryAtIndex: index])
                [self setActive: NO atIndex: index];
            else if (![qc isActiveAtIndex: index] && [qc userCanStartQueryAtIndex: index])
                [self setActive: YES atIndex: index];
        }
    }
    
    - (void) setActive: (BOOL) active atIndex: (unsigned) index; {
        if (index >= 0 && index < [qc count]) {
            AqQueryCell* cell = [qc cellAtIndex: index];
            cell->controlOpacityTarget = 1;
            cell->controlOpacity = 0;

            [qc setActive: active atIndex: index];
            
            if (active) {
                [self performSelector: @selector(stopQuery:) withObject: [qc queryAtIndex: index] afterDelay: kAqQueryCancelDelay];
            } else {
                [NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(stopQuery:) object: [qc queryAtIndex: index]];
            }
        }
    }

    - (void) stopQuery: (id) theQuery; {
        [self setActive: NO atIndex: [qc indexOfQuery: theQuery]];
    }

#pragma mark -

- (void) collapseSidebar {
     NSView *leftView=[[splitView subviews] objectAtIndex:0];
     NSView *rightView=[[splitView subviews] objectAtIndex:1];
    
     lastLeftFrame = [leftView frame];
     lastRightFrame = [rightView frame];
 
     NSRect lrFrame = lastRightFrame;
     NSRect llFrame = lastLeftFrame;
     lrFrame.size.width -= lastLeftFrame.size.width;
     llFrame.size.width = 0;
     [rightView setFrame: lrFrame];
     [leftView setFrame: llFrame];
     [splitView adjustSubviews];
     collapsed = TRUE;
 }
 
 - (void) uncollapseSidebar {
     NSView *leftView=[[splitView subviews] objectAtIndex:0];
     NSView *rightView=[[splitView subviews] objectAtIndex:1];
    
     [leftView setFrame:lastLeftFrame];
     [rightView setFrame:lastRightFrame];
 
     [splitView adjustSubviews];
     collapsed = FALSE;
 }

 - (void)splitViewDidResizeSubviews:(NSNotification *)aNotification {
        NSEvent *event = [window currentEvent];
        NSRect leftFrame = [[[splitView subviews] objectAtIndex:0] frame];
        
        if (!leftFrame.size.width) collapsed = TRUE;
        if ([event type] == NSLeftMouseDown && [event clickCount] == 2)  {
            [self toggleSidebar];
        }
 }
 
 - (BOOL)splitView:(NSSplitView *)sender  canCollapseSubview:(NSView*)subview {
    return NO;
 }
 
 - (float)splitView:(NSSplitView *)sender constrainMinCoordinate:(float)proposedMin ofSubviewAt:(int)offset {
    if (collapsed) return 0;
    return 27;
 }
 
 - (float)splitView:(NSSplitView *)sender constrainMaxCoordinate:(float)proposedMax ofSubviewAt:(int)offset {
    if (collapsed) return 0;
    return 300;
 }
 
#pragma mark -

#define NOTCONNECTED NSLocalizedStringFromTable(@"Not Connected", @"StatusBar", @"")
#define FILES NSLocalizedStringFromTable(@"%i files available", @"StatusBar", @"")
#define DOWNLOADING NSLocalizedStringFromTable(@"%i downloading at %@", @"StatusBar", @"")
#define UPLOADING NSLocalizedStringFromTable(@"%i uploading at %@", @"StatusBar", @"")

#define PANTHER (NSAppKitVersionNumber) >= 703

- (void)writeStatusBar:(NSString *)theStr {
    [statusBar setStringValue:theStr];
    //NSLog(@"StatusBar: %@", theStr);
 }

- (void)redrawStatusBar; {
    id AqDLC = [AqDownloadsController instance];
    id AqULC = [AqUploadsController instance];
    
    int fileCount = [AqNetworkController totalFiles];
    int peerCount = [AqNetworkController totalPeers];
    id theDownload;
    
    NSString* files = NOTCONNECTED;
    NSString* downloads = @"";
    NSString* uploads = @"";
    
    if (downloadForStatus >= [AqDLC total]) downloadForStatus = 0;

    if (peerCount) files = [NSString stringWithFormat: FILES, fileCount];
    if ([AqDLC active] || [AqDLC waiting]) {
        theDownload = [AqDLC downloadAtIndex: downloadForStatus];
        
        [statusBarProgress setToolTip: [theDownload name]];
        [statusBarProgress setMenu: [AqDLC menuWithDownloads: downloadForStatus]];
        
        if ([theDownload isActive]) {
            [statusBarProgress startAnimation: nil];
            [statusBarProgress setIndeterminate: NO];
            [statusBarProgress setDoubleValue: [theDownload percentComplete]];
            if (PANTHER) [statusBarProgress setHidden: NO];
        } else if ([theDownload isWaiting] && ![AqDLC active]) {
            [statusBarProgress setIndeterminate: YES];
            [statusBarProgress startAnimation: nil];
            if (PANTHER) [statusBarProgress setHidden: NO];
        } else {
            /* find another download... */
            downloadForStatus ++;
            [statusBarProgress stopAnimation: nil];
            if (PANTHER) [statusBarProgress setHidden: YES];
            else [statusBarProgress setIndeterminate: YES];
        }
    } else if (PANTHER) {
        [statusBarProgress setHidden: YES];
    } else {
        [statusBarProgress stopAnimation: nil];
        [statusBarProgress setIndeterminate: YES];                
    }

    if ([AqDLC active]) downloads = [NSString stringWithFormat: [NSString stringWithFormat: @" %@", DOWNLOADING], [AqDLC active], [AqDLC totalBandwidthString]];
    if ([AqULC active]) uploads = [NSString stringWithFormat: [NSString stringWithFormat: @" %@", UPLOADING], [AqULC active], [AqULC totalBandwidthString]];
    
    [self writeStatusBar:[NSString stringWithFormat: @"%@%@%@", files, downloads, uploads]];
 }

    + (void)redrawStatusBar; {
    [[AqDrawerController instance] redrawStatusBar];
 }

#pragma mark -

 - (unsigned int) downloadForStatus; {
    return downloadForStatus;
 }

- (void) setDownloadForStatus: (int) theVal; {
    downloadForStatus = theVal;
    [self redrawStatusBar];
 }

 + (unsigned int) downloadForStatus; {
    return [[AqDrawerController instance] downloadForStatus];
 }

 + (void) setDownloadForStatus: (int) theVal; {
    [[AqDrawerController instance] setDownloadForStatus: theVal];
 }

 + (void) setDownloadForStatusFromMenu: (id) theVal; {
    id theDL = [[AqDownloadsController instance] downloadAtIndex:[theVal tag]];
    if ([theDL isComplete]) [AqDownloadsController openStatusDownload: theVal];
    else if (![theDL isActive] && ![theDL isWaiting]) [AqDrawerController showStatusDownload: [theVal tag]];
    else [[AqDrawerController instance] setDownloadForStatus: [theVal tag]];
}
 
 - (void) showStatusDownload: (int) theDownload; {
    [self command3: nil];
    [window makeFirstResponder: [AqDownloadsController instance]->tableView];
    [[AqDownloadsController instance]->tableView selectRow: theDownload byExtendingSelection: NO];
 }
 
 + (void) showStatusDownload: (int) theDownload; {
    [[AqDrawerController instance] showStatusDownload: theDownload];
 }
 
 + (float) statusDownloadPercent; {
    if ([AqDownloadsController instance]->active > 0 && [defaults boolForKey: @"AcqProgressInDock"])
        return [[[AqDownloadsController instance] downloadAtIndex: [AqDrawerController downloadForStatus]] percentComplete];
    else return -1.0;
 }

@end