/*
 Oaxaca: Useful Cocoa Library
 Copyright (C) 2005, Niko Matsakis (niko@alum.mit.edu)
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#import "OAWorkChunker.h"


@implementation OAWorkChunker

- (void) dealloc
{
    [_object release];
    [super dealloc];
}

- (int) index
{
    return _index;
}

- (int) maxCount
{
    return _maxCount;
}

- (void) setWorkMethod:(SEL)wm
{
    _workMethod = wm;
}

- (void) scheduleMoreWork
{
    // We're now using the runModalSession system instead...
    //[[NSRunLoop currentRunLoop] performSelector:@selector(processing:)
    //                                     target:self
    //                                   argument:nil
    //                                      order:6
    //                                      modes:[NSArray arrayWithObject:@"NSDefaultRunLoopMode"]];
    _scheduled = YES;
}

- (void) workCompleted:(int)completed
{
    _index += completed;
    
    if (_indicator) {
        [_indicator setDoubleValue:(double)_index];
        [_indicator displayIfNeeded];
    }
    
    if (_index < _maxCount) {
        [self scheduleMoreWork];
    }
    else {
        [_object performSelector:_completeMethod];
    }
}

- (void) processing:arg
{
    _scheduled = NO;
    
    [_object performSelector:_workMethod withObject:self];
    
    if (!_scheduled) {
        [NSApp stopModal];
    }
}

- (IBAction) cancelProcessing:sender
{
    // XXX todo: send an alternate msg or something?
    _canceled = YES;
}

- (BOOL) canceled
{
    return _canceled;
}

- initWithObject:object
      workMethod:(SEL)wm
  completeMethod:(SEL)cm
        maxCount:(int)maxcount
          prompt:(NSString*)prompt
     allowCancel:(BOOL)cancel
{
    if ((self = [super init])) {
        _object = [object retain];
        _workMethod = wm;
        _completeMethod = cm;
        _maxCount = maxcount;
        
        [NSBundle loadNibNamed:@"OAWorkChunker" owner:self];
        
        if (cancel) {
            _panel = _cancelPanel;
            _text = _cancelText;
            _indicator = _cancelProgress;
        }
        else {
            _panel = _noCancelPanel;
            _text = _noCancelText;
            _indicator = _noCancelProgress;
        }
        
        // Set the prompt appropriately
        [_text setStringValue:prompt];
        
        // Prepare the progress indicator
        if (_maxCount >= 0) {
            [_indicator setIndeterminate:NO];
            [_indicator setMinValue:0.0];
            [_indicator setMaxValue:(double)maxcount];        
        }
        else {
            [_indicator setIndeterminate:YES];
        }
        
        // ensure we are scheduled initially
        [self scheduleMoreWork];        
        
        // Run the modal session.
        NSModalSession session = [NSApp beginModalSessionForWindow:_panel];
        @try {
            while (YES) {
                if ([NSApp runModalSession:session] != NSRunContinuesResponse)
                    break;
                [self processing:nil]; // do work
            }
        }
        @finally {
            [NSApp endModalSession:session];
        }
        
        // remove the window when proc is done
        [_panel orderOut:self];
    }
    return self;
}

+ (void) startWorkBy:object
          workMethod:(SEL)wm
      completeMethod:(SEL)cm
            maxCount:(int)maxcount
              prompt:(NSString*)prompt
         allowCancel:(BOOL)cancel
{
    [[[OAWorkChunker alloc] initWithObject:object
                                workMethod:wm
                            completeMethod:cm
                                  maxCount:maxcount
                                    prompt:prompt
                               allowCancel:cancel
        ] release];
    
}

    // Use when amount of work to be done cannot be quantified.  See description above.
+ (void) startWorkBy:object
          workMethod:(SEL)selector
              prompt:(NSString*)prompt
         allowCancel:(BOOL)cancel
{
    [[[OAWorkChunker alloc] initWithObject:object
                                workMethod:selector
                            completeMethod:@selector(NEVERUSED)
                                  maxCount:-1
                                    prompt:prompt
                               allowCancel:cancel
        ] release];
}

@end
