//
//  DefaultObjectDumpFormatter.m
//  SFS2X
//
//  Original development by Infosfer Game Technologies Ltd. | http://www.infosfer.com.
//
//  Maintained and developed by A51 Integrated.
//  Copyright 2012 A51 Integrated | http://a51integrated.com. All rights reserved.
//

#import "DefaultObjectDumpFormatter.h"
#import "SFSException.h"

NSString * const DefaultObjectDumpFormatter_TOKEN_INDENT_OPEN = @"{";
NSString * const DefaultObjectDumpFormatter_TOKEN_INDENT_CLOSE = @"}";
NSString * const DefaultObjectDumpFormatter_TOKEN_DIVIDER = @";";

NSString * const DefaultObjectDumpFormatter_NEW_LINE = @"\n";
NSString * const DefaultObjectDumpFormatter_TAB = @"\t";
NSString * const DefaultObjectDumpFormatter_DOT = @".";

NSInteger const DefaultObjectDumpFormatter_HEX_BYTES_PER_LINE = 16;


@implementation DefaultObjectDumpFormatter


+(NSString *)strFill:(NSString *)ch howMany:(NSInteger)howMany {
	NSMutableString *strBuf = [NSMutableString string];
	
	for (int i = 0; i < howMany; i++) {
		[strBuf appendString:ch];
	}
	
	return strBuf;
}

+(NSString *)getFormatTabs:(NSInteger)howMany {
	return [self strFill:DefaultObjectDumpFormatter_TAB howMany:howMany];
}

+(NSString *)prettyPrintDump:(NSString *)dump {
	
	NSMutableString *strBuf = [NSMutableString string];
	int indentPos = 0;
	
	for (int i = 0; i < [dump length]; i++) {
		
		NSRange range = {i, 1};
		NSString *ch = [dump substringWithRange:range];
		
		if ([ch isEqualToString:DefaultObjectDumpFormatter_TOKEN_INDENT_OPEN]) {
			indentPos++;
			[strBuf appendString:[NSString stringWithFormat:@"%@%@", DefaultObjectDumpFormatter_NEW_LINE, [self getFormatTabs:indentPos]]];
		}
		else if ([ch isEqualToString:DefaultObjectDumpFormatter_TOKEN_INDENT_CLOSE]) {
			indentPos--;
			if (indentPos < 0) {
				@throw [SFSException exceptionWithReason:@"DumpFormatter: the indentPos is negative. TOKENS ARE NOT BALANCED!"];
			}
			
			[strBuf appendString:[NSString stringWithFormat:@"%@%@", DefaultObjectDumpFormatter_NEW_LINE, [self getFormatTabs:indentPos]]];
		}
		else if ([ch isEqualToString:DefaultObjectDumpFormatter_TOKEN_DIVIDER]) {
			[strBuf appendString:[NSString stringWithFormat:@"%@%@", DefaultObjectDumpFormatter_NEW_LINE, [self getFormatTabs:indentPos]]];
		}
		else {
			[strBuf appendString:ch];
		}

	}
	
	if (indentPos != 0) {
		@throw [SFSException exceptionWithReason:@"DumpFormatter: the indentPos is not == 0. TOKENS ARE NOT BALANCED!"];
	}
	
	return strBuf;
}

+(NSString *)hexDump:(NSData *)data bytesPerLine:(NSInteger)bytesPerLine{
	int position = 0;
	
	if (bytesPerLine == -1) {
		bytesPerLine = DefaultObjectDumpFormatter_HEX_BYTES_PER_LINE;
	}
	
	NSMutableString *sb = [NSMutableString stringWithFormat:@"Binary Size: %ld %@", (long)[data length], DefaultObjectDumpFormatter_NEW_LINE];
	
	if ([data length] == 0) {
		return sb;
	}
	
	NSMutableString *hexLine = [NSMutableString string];
	NSMutableString *chrLine = [NSMutableString string];
	
	int index = 0;
	int count = 0;
	NSString *currChar;
	uint8_t currByte;
	
	do {
		
		NSRange range = {position, 1};
		position++;
		
		[data getBytes:&currByte range:range];
		
		NSString *hexByte = [NSString stringWithFormat:@"%02x", [[NSNumber numberWithInt:currByte] intValue]];
		[hexLine appendFormat:@"%@ ", hexByte];
		
		if (currByte >= 33 && currByte <= 126) {
			char chars[2];
			chars[0] = currByte;
			chars[1] = 0;
			
			currChar = [NSString stringWithCString:(const char *)&chars encoding:NSASCIIStringEncoding];
		}
		else {
			currChar = DefaultObjectDumpFormatter_DOT;
		}
		
		[chrLine appendString:currChar];
		
		if (++count == bytesPerLine) {
			count = 0;
			[sb appendFormat:@"%@%@%@%@", hexLine, DefaultObjectDumpFormatter_TAB, chrLine, DefaultObjectDumpFormatter_NEW_LINE];
			
			hexLine = [NSMutableString string];
			chrLine = [NSMutableString string];
		}
		
	} while (++index < [data length]);
		
		
	if (count != 0) {
		
		for (int j = (int)bytesPerLine - count; j > 0; j--) {
			[hexLine appendString:@"   "];
			[chrLine appendString:@" "];
		}
		
		[sb appendFormat:@"%@%@%@%@", hexLine, DefaultObjectDumpFormatter_TAB, chrLine, DefaultObjectDumpFormatter_NEW_LINE];
		
	}
	
	return sb;
	
}


@end
