/*
 *	Filename: RegExFormatter.m
 *	Created : Mon Jan 20 12:49:00 1997
 *	Author  : Vince DeMarco
 *	LastEditDate Was "Thu Jan 23 10:08:56 1997"
 */


#import "RegExFormatter.h"

#import <Foundation/Foundation.h>

#import <regex/RegEx.h>
#import <regex/RegExMatcher.h>
#import "NSString_ext.h"

/* Keys used when reading the configuration from a dictionary file
 * loaded from disk
 */
NSString *RegExFormatterRegex      = @"RegExFormatterRegex";
NSString *RegExFormatterFormatter  = @"RegExFormatterFormatter";
NSString *RegExFormatterAllowEmpty = @"RegExFormatterAllowEmpty";

@implementation RegExFormatter


- (id)initWithContentsOfFile:(NSString *)path
{
    NSDictionary *dict;
    NSEnumerator *enu;
    NSString     *obj;
    BOOL          allowEmpty;

    dict = [[NSDictionary allocWithZone:[self zone]] initWithContentsOfFile:path];

    [self init];
    enu = [[dict objectForKey:RegExFormatterRegex] objectEnumerator];

    if ([[dict objectForKey:RegExFormatterAllowEmpty] compare:@"YES" options:NSCaseInsensitiveSearch] == NSOrderedSame){
	allowEmpty = YES;
    }else{
	allowEmpty = NO;
    }

    while((obj = [enu nextObject])){
	[self addRegularExpression:[RegEx regexWithPattern:obj]];
    }

    [self setFormatPattern:[dict objectForKey:RegExFormatterFormatter]];
    [self setAllowsEmptyString:allowEmpty];
    [dict release];

    return self;
}

/* Designated initalizer */
- (id)initWithRegularExpressions:(NSArray *)expressions
{
    [super init];

    if (expressions){
	_expressions = [[NSMutableArray allocWithZone:[self zone]] initWithArray:expressions];
    }else{
	_expressions = [[NSMutableArray allocWithZone:[self zone]] init];
    }
    [self setAllowsEmptyString:YES];
    [self setFormatPattern:@"%0"];
    _lastMatchedExpression = nil;
    return self;
}

- (id)initWithRegularExpression:(RegEx *)expression
{
    return [self initWithRegularExpressions:(expression ? [NSArray arrayWithObject: expression] : nil)];
}

- (id)init
{
    return [self initWithRegularExpressions:nil];
}

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

/* NSCopying Protocol */
- (id)copyWithZone:(NSZone *)zone
{
    return [self initWithRegularExpressions:_expressions];
}

/* NSCoding Procotol */
- (void)encodeWithCoder:(NSCoder *)coder
{
    BOOL allowsEmptyString = [self allowsEmptyString];

    [super encodeWithCoder:coder];
    [coder encodeObject:_expressions];
    [coder encodeObject:_formatPattern];
    [coder encodeValueOfObjCType:"C" at:&allowsEmptyString];
}

- (id)initWithCoder:(NSCoder *)coder
{
    BOOL allowsEmptyString;

    self	   = [super initWithCoder:coder];
    _expressions   = [[coder decodeObject] retain];
    _formatPattern = [[coder decodeObject] retain];
    [coder decodeValueOfObjCType:"C" at:&allowsEmptyString];
    [self setAllowsEmptyString:allowsEmptyString];
    _lastMatchedExpression = nil;
    return self;
}

- (void)addRegularExpression:(RegEx *)expression
{
    if (expression){
	[_expressions addObject:expression];
    }
}

- (void)removeRegularExpressionAtIndex:(unsigned)index
{
	//NSParameterAssert(index >= 0 && [_expressions count] <= index);
    [_expressions removeObjectAtIndex:index];
}

- (RegEx *)regularExpressionAtIndex:(unsigned)index
{
    return [[self expressions] objectAtIndex:index];
}

- (NSArray *)expressions
{
    return _expressions;
}

- (BOOL)allowsEmptyString
{
    return _allowsEmptyString;
}

- (void)setAllowsEmptyString:(BOOL)flag
{
    _allowsEmptyString = flag;
}

- (NSString *)formatPattern
{
    return _formatPattern;
}

- (void)setFormatPattern:(NSString *)pattern
{
    [_formatPattern autorelease];
    _formatPattern = [pattern retain];
}

- (RegEx *)lastMatchedExpression
{
    return _lastMatchedExpression;
}

- (NSString *)stringForObjectValue:(id)anObject
{
    if (![anObject isKindOfClass:[NSString class]]){
	return @"";
    }

    if ([(NSString *)anObject isEqual:@""] && [self allowsEmptyString]){
	return anObject;
    }else{
	_lastMatchedExpression = [[self expressions] regExMatching:(NSString *)anObject];
	if (_lastMatchedExpression){
	    return [NSString stringWithFormat:[self formatPattern]
			                array:[_lastMatchedExpression stringWithComponents:anObject]];
	}else{
	    return anObject;
	}
    }
}

- (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error
{
    if ([string isEqual:@""] && [self allowsEmptyString]){
	if (anObject){
	    *anObject = string;
	}
	return YES;
    }else{
	_lastMatchedExpression = [[self expressions] regExMatching:string];
	if (_lastMatchedExpression){
	    if (anObject){
		*anObject = [NSString concatenateStringsFromArray:[_lastMatchedExpression stringWithComponents:string]];
	    }
	    return YES;
	}else{
	    if (error){
		*error = [NSString
			     stringWithFormat:@"Proposed value '%@' failed to format formatter has no expressions to match.",
			     string];
	    }
	}
    }
    return NO;
}

- (NSString *)description
{
    return [[self expressions] description];
}

@end
