/*
    DAAC_AppController.m

    Copyright 2008,2009 Josh Freeman
    http://www.twilightedge.com

    This file is part of DAA Converter v1.3 for Mac OS X.

    DAA Converter 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, see <http://www.gnu.org/licenses/>.
*/

#import "DAAC_AppController.h"

#import "DAAC_UIController.h"
#import "DAAC_ConversionTask.h"
#import "DAAC_FilenameUtilities.h"
#import "DAAC_Strings.h"


@interface DAAC_AppController (PrivateMethods)

- (bool) enqueueDAAFileForConversion: (NSString *) daaFilepath;
- (bool) enqueueDAAFilesForConversion: (NSArray *) daaFilepaths;

- (void) startConvertingNextDAAFile;
- (void) stopConverting;

@end

@implementation DAAC_AppController

- init
{
    self = [super init];

    if (self)
    {
        _daaFilesToConvert = [[NSMutableArray array] retain];

        if (!_daaFilesToConvert)
            goto ERROR;
    }

    return self;

ERROR:
    [self release];

    return nil;
}

- (void) dealloc
{
    if (_conversionTask)
        [self stopConverting];

    [_daaFilesToConvert release];

    [super dealloc];
}

#pragma mark NSApplication Delegate Methods

- (BOOL) application: (NSApplication *) theApplication openFile: (NSString *) filepath
{
    return ([self enqueueDAAFileForConversion: filepath]) ? YES : NO;
}

- (void) application: (NSApplication *) sender openFiles: (NSArray *) filepaths
{
    if ([self enqueueDAAFilesForConversion: filepaths])
    {
        [sender replyToOpenOrPrint: NSApplicationDelegateReplySuccess];
    }
    else
    {
        [sender replyToOpenOrPrint: NSApplicationDelegateReplyFailure];
    }
}

- (void) applicationDidFinishLaunching: (NSNotification *) aNotification
{
    if ([_daaFilesToConvert count])
    {
        [self startConvertingNextDAAFile];
    }
    else
    {
        [_uiController promptForFilesToConvert];
    }
}

- (void) applicationWillTerminate: (NSNotification *) aNotification
{
    if (_conversionTask)
        [self stopConverting];
}

- (BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication *) theApplication
{
    return YES;
}

#pragma mark File Queueing

- (bool) enqueueDAAFileForConversion: (NSString *) daaFilepath
{
    // a DAA archive may be split across multiple files, so to prevent the archive from being
    // enqueued multiple times when more than one of its files are selected, use the archive's
    // primary path (path to its first file)
    daaFilepath = PrimaryDAAFilepathForDAAFilepath(daaFilepath);

    if (daaFilepath && ![_daaFilesToConvert containsObject: daaFilepath])
    {
        [_daaFilesToConvert addObject: daaFilepath];

        [_uiController updateTotalNumberOfConversions: [_daaFilesToConvert count]];

        return YES;
    }

    return NO;
}

- (bool) enqueueDAAFilesForConversion: (NSArray *) daaFilepaths
{
    NSEnumerator *enumerator;
    NSString *daaFilepath;
    bool fileWasEnqueued = NO;

    if (![daaFilepaths count])
        return NO;

    enumerator = [daaFilepaths objectEnumerator];

    while (daaFilepath = [enumerator nextObject])
    {
        if ([self enqueueDAAFileForConversion: daaFilepath])
            fileWasEnqueued = YES;
    }

    return fileWasEnqueued;
}

#pragma mark Conversion

- (void) startConvertingNextDAAFile
{
    NSString *daaFilepath, *isoFilepath;

    if (_conversionTask)
        goto ERROR;

    // quit when there's no files left to convert
    if (_indexOfNextDAAFileToConvert >= [_daaFilesToConvert count])
    {
        [NSApp terminate: self];
        return;
    }

    daaFilepath = [_daaFilesToConvert objectAtIndex: _indexOfNextDAAFileToConvert++];

    if (![daaFilepath length])
        goto ERROR;

    isoFilepath = PathToNonexistentFileInDirectoryWithPreferredFilename(
                                [daaFilepath stringByDeletingLastPathComponent],
                                ISOFilenameForDAAFilename([daaFilepath lastPathComponent]));

    if (![isoFilepath length])
        goto ERROR;

    if (![_uiController setupForNewConversionWithTargetFilename: [isoFilepath lastPathComponent]
                                            conversionNumber: _indexOfNextDAAFileToConvert])
    {
        goto ERROR;
    }

    _conversionTask = [[DAAC_ConversionTask conversionTaskWithSourceDAAFile: daaFilepath
                                                            targetISOFile: isoFilepath
                                                                delegate: self]
                                retain];

    if (!_conversionTask)
        goto ERROR;

    return;

ERROR:
    [_uiController displayErrorMessage: kErrorMessage_UnknownError];
}

- (void) stopConverting
{
    [_conversionTask cancel];
    [_conversionTask release];
    _conversionTask = nil;
}

#pragma mark UIController Delegate Methods

- (void) uiControllerSelectedFilesToConvert: (NSArray *) filepaths
{
    [self enqueueDAAFilesForConversion: filepaths];

    if ([_daaFilesToConvert count])
    {
        [self startConvertingNextDAAFile];
    }
    else
    {
        [_uiController displayErrorMessage: kErrorMessage_UnknownError];
    }
}

- (void) uiControllerReceivedPassword: (NSString *) password
{
    [_conversionTask submitEncryptionPassword: password];
}

- (void) uiControllerReceivedCancel
{
    [NSApp terminate: self];
}

- (void) uiControllerFinishedDisplayingErrorMessage
{
    [NSApp terminate: self];
}

- (void) uiControllerNeedsConversionToolCreditsForAboutBox: (NSString **) returnedToolCredits
{
    if (returnedToolCredits)
        *returnedToolCredits = [DAAC_ConversionTask daa2isoCredits];
}

#pragma mark ConversionTask Delegate Methods

- (void) conversionTaskCompletedSuccessfully: (DAAC_ConversionTask *) conversionTask
{
    [self stopConverting];
    [self startConvertingNextDAAFile];
}

- (void) conversionTask: (DAAC_ConversionTask *) conversionTask
            failedOnDAAFile: (NSString *) daaFilename
            withErrorMessage: (NSString *) errorMessage
{
    [_uiController updateConversionSourceFilename: daaFilename];
    [_uiController displayErrorMessage: errorMessage];
}

- (void) conversionTask: (DAAC_ConversionTask *) conversionTask
            openedDAAFile: (NSString *) filename
{
    [_uiController updateConversionSourceFilename: filename];
}

- (void) conversionTask: (DAAC_ConversionTask *) conversionTask
            didProgress: (unsigned) completionPercentage
{
    [_uiController updateConversionProgress: completionPercentage];
}

- (void) conversionTaskRequiresEncryptionPassword: (DAAC_ConversionTask *) conversionTask
{
    [_uiController promptForPassword];
}

@end
