/*
    DAAC_DAA2ISOTaskOutputParsing.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_DAA2ISOTaskOutputParsing.h"

#import "DAAC_Strings.h"


#define kDAA2ISOTaskOutputPattern_OpenedNewSourceFile       @"open "
#define kDAA2ISOTaskOutputPattern_UnknownDAAVersionAlert    @"Alert: unknown DAA version"
#define kDAA2ISOTaskOutputPattern_PasswordRequest           @"protected by password, insert it:"
#define kDAA2ISOTaskOutputPattern_ErrorMessage              @"Error: "
#define kDAA2ISOTaskOutputPattern_ConversionStarted         @"- start unpacking:"
#define kDAA2ISOTaskOutputPattern_ConversionFinished        @"- finished"
#define kDAA2ISOTaskOutputPattern_CompletionPercentage      @"%"
#define kDAA2ISOTaskOutputPattern_CreditsCutoff             @"Usage:"

#define kDAA2ISOTaskOutput_CompletionPercentageNumDigits    3

#define kErrorMessagePattern_WrongDAASignature              @"wrong DAA signature"


static bool InitializeParsingGlobals(void);


static NSCharacterSet *gNonWhitespaceAndNewlineCharacterSet = nil;
static bool gParsingGlobalsAreInitialized = NO;


static bool InitializeParsingGlobals(void)
{
    if (gParsingGlobalsAreInitialized)
        return YES;

    gNonWhitespaceAndNewlineCharacterSet =
                    [[[NSCharacterSet whitespaceAndNewlineCharacterSet] invertedSet] retain];

    if (!gNonWhitespaceAndNewlineCharacterSet)
        return NO;

    gParsingGlobalsAreInitialized = YES;

    return YES;
}

bool DAA2ISOTaskOutput_HasNewDAASourceFile(NSString *outputString,
                                            NSString **returnedDAAFilename)
{
    NSRange range, filenameRange;
    NSString *newDAAFilename;

    range = [outputString rangeOfString: kDAA2ISOTaskOutputPattern_OpenedNewSourceFile
                                options: NSBackwardsSearch];

    if (range.length)
    {
        range.location += [kDAA2ISOTaskOutputPattern_OpenedNewSourceFile length];

        if (range.location < [outputString length])
        {
            filenameRange.location = range.location;
            range = [[outputString substringFromIndex: range.location] rangeOfString: @"\n"];

            if (range.length && range.location)
            {
                filenameRange.length = range.location;

                newDAAFilename = [outputString substringWithRange: filenameRange];

                if ([newDAAFilename length])
                {
                    if (returnedDAAFilename)
                        *returnedDAAFilename = newDAAFilename;

                    return YES;
                }
            }
        }
    }

    return NO;
}

bool DAA2ISOTaskOutput_HasUnknownDAAVersionAlert(NSString *outputString)
{
    return ([outputString
                    rangeOfString: kDAA2ISOTaskOutputPattern_UnknownDAAVersionAlert].length) ?
                YES : NO;
}

bool DAA2ISOTaskOutput_HasPasswordRequest(NSString *outputString)
{
    return ([outputString rangeOfString: kDAA2ISOTaskOutputPattern_PasswordRequest].length) ?
                YES : NO;
}

bool DAA2ISOTaskOutput_HasErrorMessage(NSString *outputString, NSString **returnedErrorMessage)
{
    NSRange range, errorMessageRange;
    NSString *errorMessage = nil;

    if (!gParsingGlobalsAreInitialized && !InitializeParsingGlobals())
        return NO;

    range = [outputString rangeOfString: kDAA2ISOTaskOutputPattern_ErrorMessage];

    if (!range.length)
        return NO;

    errorMessageRange.location = range.location;

    range = [outputString rangeOfCharacterFromSet: gNonWhitespaceAndNewlineCharacterSet
                                         options: NSBackwardsSearch];

    if (range.length && (range.location > errorMessageRange.location))
    {
        errorMessageRange.length = range.location - errorMessageRange.location + 1;
        errorMessage = [outputString substringWithRange: errorMessageRange];
    }

    // special handling for "wrong DAA signature" error: daa2iso will ask if the user wants to
    // continue despite the wrong signature, but DAA Converter hasn't yet implemented GUI
    // support for this query, so for the moment it's just treated as a non-recoverable error;
    // this means the error message should be clipped to its first line to remove the question
    // about whether to continue (the query is on the second line)
    if ([errorMessage rangeOfString: kErrorMessagePattern_WrongDAASignature].length)
    {
        range = [errorMessage rangeOfString: @"\n"];
        
        if (range.length && range.location)
            errorMessage = [errorMessage substringToIndex: range.location];
    }

    if (!errorMessage)
        errorMessage = kErrorMessage_UnknownError;

    if (returnedErrorMessage)
        *returnedErrorMessage = errorMessage;

    return YES;
}

bool DAA2ISOTaskOutput_HasConversionBegun(NSString *outputString)
{
    return ([outputString rangeOfString: kDAA2ISOTaskOutputPattern_ConversionStarted].length) ?
                YES : NO;
}

bool DAA2ISOTaskOutput_HasConversionFinished(NSString *outputString)
{
    return ([outputString
                    rangeOfString: kDAA2ISOTaskOutputPattern_ConversionFinished].length) ?
                YES : NO;
}

bool DAA2ISOTaskOutput_HasConversionProgress(NSString *outputString,
                                                unsigned *returnedCompletionPercentage)
{
    NSRange range;

    range = [outputString rangeOfString: kDAA2ISOTaskOutputPattern_CompletionPercentage
                                options: NSBackwardsSearch];

    if (range.length && (range.location >= kDAA2ISOTaskOutput_CompletionPercentageNumDigits))
    {
        range.location -= kDAA2ISOTaskOutput_CompletionPercentageNumDigits;
        range.length = kDAA2ISOTaskOutput_CompletionPercentageNumDigits;

        if (returnedCompletionPercentage)
        {
            *returnedCompletionPercentage =
                                (unsigned) [[outputString substringWithRange: range] intValue];
        }

        return YES;
    }

    return NO;
}

bool DAA2ISOTaskOutput_RetrieveCredits(NSString *outputString, NSString **returnedCredits)
{
    NSRange range;
    NSString *daa2isoCredits;

    if (!gParsingGlobalsAreInitialized && !InitializeParsingGlobals())
        return NO;

    range = [outputString rangeOfString: kDAA2ISOTaskOutputPattern_CreditsCutoff];

    if (!range.length || !range.location)
        return NO;

    range = [outputString rangeOfCharacterFromSet: gNonWhitespaceAndNewlineCharacterSet
                                        options: NSBackwardsSearch
                                        range: NSMakeRange(0, range.location)];

    if (!range.length)
        return NO;

    daa2isoCredits = [outputString substringToIndex: range.location + 1];

    if (![daa2isoCredits length])
        return NO;

    if (returnedCredits)
        *returnedCredits = daa2isoCredits;

    return YES;
}
