//
//  FTToolBox.m
//
//  FelineTek iPhone ToolBox. Copyright (C) 2009 FelineTek.
//
//  FelineTek iPhone ToolBox is free software; you can redistribute it 
//  and/or modify it under the terms of the GNU Lesser General Public
//  License (LGPL) as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library 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
//  Lesser General Public License for more details.
//
//  For more info see http://www.felinetek.com/FTToolbox
//
//  Created by Panos Hadjikomninos on 13/03/2009.
//  Copyright (C) 2009 FelineTek. All rights reserved.
//

#import "FTToolBox.h"


@implementation FTToolBox





#pragma mark -
#pragma mark Logging  Utilities


static BOOL logDisabled=NO;
static BOOL logInitialized=NO;
static int  presetSeverity=FT_ANALYTIC;


static NSArray *severityText;

static NSMutableArray *logFT;
static int	logIndex=0;
static BOOL maxExceeded=NO;

static NSFileHandle *logFile;





+ (void) FTinitializeLog:(BOOL) debug atLevel: (int) level
{
	
	presetSeverity = level;
	logDisabled = (!debug);
	
	@synchronized([FTToolBox class]) { 
		
		logInitialized=YES;
		
		severityText = [NSArray arrayWithObjects:@"UNRECOVERABLE",@"CRITICAL",@"ERROR",@"WARNING",@"INFORMATION",@"DEBUGGING",@"ANALYTIC",@"VERBOSE",nil];
		
		[severityText retain];
		
		logFT =[[NSMutableArray alloc] initWithCapacity:FT_LOG_MAX];
		[logFT retain];
		
		for (int i=0; i < FT_LOG_MAX; i++) {
			[logFT addObject:@"-"];
		}
		
		
		// Copy Log to Crash Log
		// ---------------------
		NSString *path = [NSString stringWithString:[FTToolBox getFilePath:@"log.dat"]];	
		logFile = [NSFileHandle fileHandleForReadingAtPath:path];
		[logFile retain];
		
		if (logFile != nil) {
			
			NSArray *nsa = [[[NSString alloc] initWithData: [logFile availableData] encoding: NSUTF8StringEncoding] componentsSeparatedByString:@"\n"];
			[nsa retain];
			[logFile closeFile];
			[logFile release];
			
			
			NSString *path2 = [NSString stringWithString:[FTToolBox getFilePath:@"log.bak"]];
			[[NSFileManager defaultManager] createFileAtPath:path2 contents:[NSData data] attributes:nil];
			
			NSFileHandle *crashFile = [NSFileHandle fileHandleForWritingAtPath:path2];
			[crashFile retain];
			
			if (crashFile != nil) {
				
				for (int i =0 ; i<[nsa count]; i++) {
					NSString *line = [NSString stringWithFormat:@"%@%@",[nsa objectAtIndex:i],@"\n"];
					[crashFile writeData:[line dataUsingEncoding:NSASCIIStringEncoding]];
				}
				
				[crashFile closeFile];
				[crashFile release];
			}
			
			[nsa release];
			
		}
		
		// Prepare For Write To Log
		// ------------------------
		
		[[NSFileManager defaultManager] createFileAtPath:path contents:[NSData data] attributes:nil];
		
		logFile = [NSFileHandle fileHandleForWritingAtPath:path];
		[logFile retain];
		
		
	}
}




+ (NSString *) FTseverityText: (int) severity
{
	NSString * str = [[[NSString alloc] initWithString:[severityText objectAtIndex:severity]] autorelease];
	
	return str;
	
}





+ (void) FTdirectLog:(NSString *) message
{
	[logFT replaceObjectAtIndex:logIndex withObject:message];
	logIndex++;
	
	if (logIndex == FT_LOG_MAX) {
		logIndex=0;
		maxExceeded=YES;
	}
}


+ (NSString *) FTgetLogAsString
{
	
	// !!! ATTN !!! Dont Put a Log in THIS funcion as it Exponentially increases logged text !!!
	// -----------------------------------------------------------------------------------------
	NSMutableString *buffer=[[NSMutableString alloc] initWithCapacity:1000];
	
	[buffer setString:@""];
	
	if (maxExceeded) {
		for (int i=logIndex; i < FT_LOG_MAX; i++) {
			[buffer appendString:[logFT objectAtIndex:i]];
			[buffer appendString:@"\r\n"];
		}	
	}
	
	for (int i=0; i < logIndex; i++) {
		[buffer appendString:[logFT objectAtIndex:i]];
		[buffer appendString:@"\r\n"];
	}
	
	NSString *str = [[NSString stringWithString:buffer] autorelease];
	
	[buffer release];
	
	return str;
}



+ (NSArray *) FTgetLogAsArray
{
	
	// !!! ATTN !!! Dont Put a Log in THIS funcion as it Exponentially increases logged text !!!
	// -----------------------------------------------------------------------------------------
	NSMutableArray *buffer=[[[NSMutableArray alloc] initWithCapacity:500] autorelease];
	
	
	if (maxExceeded) {
		for (int i=logIndex; i < FT_LOG_MAX; i++) {
			[buffer addObject:[logFT objectAtIndex:i]];
		}	
	}
	
	for (int i=0; i < logIndex; i++) {
		[buffer addObject:[logFT objectAtIndex:i]];
	}
	
	return buffer;
}



+ (NSArray *) FTgetCrashLogAsArray
{
	
	// !!! ATTN !!! Dont Put a Log in THIS funcion as it Exponentially increases logged text !!!
	// -----------------------------------------------------------------------------------------
	NSString *path = [NSString stringWithString:[FTToolBox getFilePath:@"log.bak"]];	
	NSFileHandle *crashFile = [NSFileHandle fileHandleForReadingAtPath:path];
	[crashFile retain];
	
	if (crashFile != nil) {
		
		NSArray *buffer = [[[NSArray alloc] initWithArray:[[[NSString alloc] initWithData: [crashFile availableData] encoding: NSUTF8StringEncoding] componentsSeparatedByString:@"\n"]] autorelease];
		
		[crashFile closeFile];
		[crashFile release];
		
		return buffer;
	}
	
	return nil;
}



+ (NSString *) FTgetCrashLogAsString
{
	
	// !!! ATTN !!! Dont Put a Log in THIS funcion as it Exponentially increases logged text !!!
	// -----------------------------------------------------------------------------------------
	NSString *path = [NSString stringWithString:[FTToolBox getFilePath:@"log.bak"]];	
	NSFileHandle *crashFile = [NSFileHandle fileHandleForReadingAtPath:path];
	[crashFile retain];
	
	if (crashFile != nil) {
		
		NSString *buffer = [[[NSString alloc] initWithString:[[NSString alloc] initWithData: [crashFile availableData] encoding: NSUTF8StringEncoding]] autorelease];
		
		[crashFile closeFile];
		[crashFile release];
		
		return buffer;
	}
	
	return nil;
}



+ (void) FTenableLog
{
	logDisabled=YES;
}



+ (void) FTdisableLog
{
	logDisabled=NO;
}



+ (BOOL) FTisLogEnabled
{
	return(!logDisabled);
}



+ (void) FTsetLogSeverity:(int) severity
{
	presetSeverity=severity;
}


+ (void) FTcloseLog
{
	[logFile closeFile];
	
}



+ (void) FTLog:(int) severity: (NSString *) message
{
	
	if (logDisabled) return;
	
	if ((severity == FT_VERBOSE) && (presetSeverity != FT_VERBOSE)) return;
	
	if (!logInitialized)
		[FTToolBox FTinitializeLog];
	
	if (severity <= presetSeverity) {	
		
		NSString * messageComplet = [NSString stringWithFormat:@"FT_%@(%i):: %@!",[severityText objectAtIndex:severity], severity, message];
		
		NSLog(@"%@",messageComplet);
		
		[FTToolBox FTdirectLog:messageComplet];
		
		NSString *line = [NSString stringWithFormat:@"%@%@",messageComplet,@"\n"];
		[logFile writeData:[line dataUsingEncoding:NSASCIIStringEncoding]];
		
		if (severity <= FT_ERROR) 
			[FTToolBox FTalertSimple:messageComplet title:@"ERROR"];	
		
		if (severity <= FT_UNRECOVERABLE) 
			[NSThread exit];	
	}		  
}






#pragma mark -
#pragma mark Animation  Utilities


+ (void) FTstdViewAnimStart
{
	[UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:0.5];
}




+ (void) FTstdViewAnimEnd
{
	[UIView commitAnimations];
}




static CATransition * animation;

+ (void) FTAnimationPrepare:(NSString *) type : (NSString *) subtype
{
	
	animation = [CATransition animation];
	[animation setDuration:0.5];
	[animation setType:type];
	[animation setSubtype:subtype];
	[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
	
	
}


+ (void) FTAnimationExecute:(UIView *) view
{
	[[view layer] addAnimation:animation forKey:@"stdAnimation"];
	
}





#pragma mark -
#pragma mark  Utilities


+ (void)FTdialogSimple: (NSString *) message view:(UIView *) view
{
	
	UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:message delegate:nil cancelButtonTitle:nil destructiveButtonTitle:@"OK" otherButtonTitles:nil];
	
	actionSheet.actionSheetStyle = UIActionSheetStyleDefault;
	
	[actionSheet showInView:view];
	
	[actionSheet release];
}





+ (void)FTalertSimple: (NSString *) message title:(NSString *) title
{
	
	UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
	
	[alert show];	
	
	[alert release];
}



+(NSString *) getFilePath:(NSString *) file
{
	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
	
    if (!documentsDirectory) {
        NSLog(@"Documents directory not found!");
        return nil;
    }
	
	NSString *appFile = [[[NSString alloc] initWithString:[documentsDirectory stringByAppendingPathComponent:file]] autorelease];
	
	return appFile;
}





#pragma mark -
#pragma mark   -----------------------------------------------------------------
#pragma mark   FREE FUNCTIONS        
#pragma mark   -----------------------------------------------------------------





#pragma mark -
#pragma mark Bitmap Context


void * bitmapData; 


// GLOBAL: USE ONCE AT A TIME ONLY, THEN FREE
// ------------------------------------------
CGContextRef GLOBALSingleBitmapContextCreateWithAlloc (int pixelsWide, int pixelsHigh) 
{ 
    CGContextRef    context = NULL; 
    CGColorSpaceRef colorSpace; 
	
    int             bitmapByteCount; 
    int             bitmapBytesPerRow; 
	
    bitmapBytesPerRow   = (pixelsWide * 4); 
    bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh); 
	
    colorSpace = CGColorSpaceCreateDeviceRGB(); 
	
    bitmapData = malloc( bitmapByteCount ); 
    if (bitmapData == NULL) 
    { 
        fprintf (stderr, "FF_ERROR:: FREE FUNCTION GLOBALSingleBitmapContextCreateWithAlloc: Memory not allocated!"); 
        return NULL; 
    } 
	
    context = CGBitmapContextCreate (bitmapData, 
									 pixelsWide, 
									 pixelsHigh, 
									 8,      
									 bitmapBytesPerRow, 
									 colorSpace, 
									 kCGImageAlphaPremultipliedLast); 
    if (context== NULL) 
    { 
        free (bitmapData); 
        fprintf (stderr, "FF_ERROR:: FREE FUNCTION GLOBALSingleBitmapContextCreateWithAlloc: Context not created!"); 
        return NULL; 
    } 
	
    CGColorSpaceRelease( colorSpace ); 
    return context; 
} 




void GLOBALSingleBitmapContextFree() 
{
	if (bitmapData == NULL) {
		fprintf (stderr, "FF_ERROR:: FREE FUNCTION GLOBALSingleBitmapContextFree: Nothing to Free!");
		return;
	}
	
	free (bitmapData);
}



@end








