//
//  MTLLoader.m
//  Lesson37_OSXCocoa
//
//  Created by Will Thimbleby on Tue Sep 02 2003.
//  Copyright (c) 2003 __MyCompanyName__. All rights reserved.
//

#import "MTLLoader.h"

GLuint GetOpenGLTexture(NSImage *image)
{
	NSArray				*reps;
	NSBitmapImageRep	*bitmapRep;
	int					i, samples, bits, width, height;
	BOOL				alpha;
	GLuint				texName;
	GLenum				type, format;
	
	reps = [image representations];
	
	for(i=0;i<[reps count];i++)
	{
		if([[reps objectAtIndex:i] isKindOfClass:[NSBitmapImageRep class]])
		{
			bitmapRep = [reps objectAtIndex:i];
			
			if([bitmapRep isPlanar])
			{
				NSLog(@"GetOpenGLTexture: Can't handle planar images.");
				return -1;
			}
			
			// get image data
			samples = [bitmapRep samplesPerPixel];
			bits = [bitmapRep bitsPerPixel];
			alpha = [bitmapRep hasAlpha];
			width = [bitmapRep pixelsWide];
			height = [bitmapRep pixelsHigh];
		}
	}
	
	glGenTextures(1, &texName);
	glBindTexture(GL_TEXTURE_2D, texName);
	
	if(alpha)
		bits *= 0.75;
	
	switch(bits)
	{
		case 24:
			type = GL_UNSIGNED_BYTE;
			break;
		case 48:
			type = GL_UNSIGNED_SHORT;
			break;
		case 96:
			type = GL_UNSIGNED_INT;
			break;
		default:
			NSLog(@"GetOpenGLTexture: Can't handle bits per pixel of %d.", bits);
			return -1;
	}
	
	if(alpha)
		format = GL_RGBA;
	else
		format = GL_RGB;
		
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, [bitmapRep bitmapData]);
	
	return texName;
}

GLuint GetOpenGLTextureFromPath(NSString *path) 
{ 
	NSBitmapImageRep	*bitmapRep; 
	int					samples, bits, width, height; 
	BOOL				alpha; 
	GLuint				texName; 
	GLenum				type, format; 
 	
	bitmapRep = [NSBitmapImageRep imageRepWithContentsOfFile:path]; 
 	
	if([bitmapRep isPlanar]) 
	{ 
		NSLog(@"GetOpenGLTexture: Can't handle planar images."); 
		return -1; 
	} 
 	
	// get image data 
	samples = [bitmapRep samplesPerPixel]; 
	bits = [bitmapRep bitsPerPixel]; 
	alpha = [bitmapRep hasAlpha]; 
	width = [bitmapRep pixelsWide]; 
	height = [bitmapRep pixelsHigh]; 

	if(alpha) 
	{ 
		samples --; 
		bits *= 0.75; 
	} 
 	
	switch(bits/samples) 
	{ 
		case 8: 
			type = GL_UNSIGNED_BYTE; 
			break; 
		case 16: 
			type = GL_UNSIGNED_SHORT; 
			break; 
		case 32: 
			type = GL_UNSIGNED_INT; 
			break; 
		default: 
			NSLog(@"GetOpenGLTexture: Can't handle bits per sample of %d/%d.", bits, samples); 
			return -1; 
	} 
 	
	switch(samples) 
	{ 
		case 3: 
			format = alpha? GL_RGBA : GL_RGB; 
			break; 
		case 1: 
			format = alpha? GL_LUMINANCE_ALPHA : GL_LUMINANCE; 
			break; 
		default: 
			NSLog(@"GetOpenGLTexture sample confused: %d, %d, %d, %d, %d", samples, bits, alpha, width, height); 
			return -1; 
	} 
 	

	//generate the texture 
	glGenTextures(1, &texName); 
	glBindTexture(GL_TEXTURE_2D, texName);
	
	
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	
	
	glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, [bitmapRep bitmapData]); 
 	
	return texName; 
}


@implementation MTLLoader

-(id) initWithFile:(NSString*)path
{
	NSString		*mtlString, *line;
	NSScanner		*scan;
	int				location = 0;
	NSRange			lineRange;
	
	float			r, g, b;
	NSString		*textureName;
	
	[super init];
	
	materialCount = -1;
	
	mtlString = [NSString stringWithContentsOfFile:path];
	
	while(location < [mtlString length])
	{
		lineRange = [mtlString lineRangeForRange:NSMakeRange(location, 0)];
		line = [mtlString substringWithRange:lineRange];
		
		location += lineRange.length;
		
		
		if([line hasPrefix:@"#"])
			continue;
		else if([line hasPrefix:@"newmtl"])
		{	
			materialCount++;
			
			scan = [NSScanner scannerWithString:line];
			[scan scanString:@"newmtl" intoString:nil];
			[scan scanUpToString:@"\r" intoString:&(materials[materialCount].name)];
			[materials[materialCount].name retain];
			
			materials[materialCount].textureMap = -1;
		}
		else if([line hasPrefix:@"Ns"])
		{
			scan = [NSScanner scannerWithString:line];
			[scan scanString:@"Ns" intoString:nil];
			
			[scan scanFloat:&(materials[materialCount].shininess)];
		}
		else if([line hasPrefix:@"illum"])
		{
			int		lighting;
			
			scan = [NSScanner scannerWithString:line];
			[scan scanString:@"illum" intoString:nil];
			
			[scan scanInt:&(materials[materialCount].lightingStyle)];
		}
		else if([line hasPrefix:@"Kd"])
		{	
			scan = [NSScanner scannerWithString:line];
			[scan scanString:@"Kd" intoString:nil];
			
			[scan scanFloat:&r];
			[scan scanFloat:&g];
			[scan scanFloat:&b];
			materials[materialCount].diffuseColor.r = r;
			materials[materialCount].diffuseColor.g = g;
			materials[materialCount].diffuseColor.b = b;
		}
		else if([line hasPrefix:@"Ka"])
		{	
			scan = [NSScanner scannerWithString:line];
			[scan scanString:@"Ka" intoString:nil];
			
			[scan scanFloat:&r];
			[scan scanFloat:&g];
			[scan scanFloat:&b];
			materials[materialCount].ambientColor.r = r;
			materials[materialCount].ambientColor.g = g;
			materials[materialCount].ambientColor.b = b;
		}
		else if([line hasPrefix:@"Ks"])
		{	
			scan = [NSScanner scannerWithString:line];
			[scan scanString:@"Ks" intoString:nil];
			
			[scan scanFloat:&r];
			[scan scanFloat:&g];
			[scan scanFloat:&b];
			materials[materialCount].specularColor.r = r;
			materials[materialCount].specularColor.g = g;
			materials[materialCount].specularColor.b = b;
		}
		else if([line hasPrefix:@"map_Kd"])
		{	
			scan = [NSScanner scannerWithString:line];
			[scan scanString:@"map_Kd" intoString:nil];
			
			[scan scanUpToString:@"\r" intoString:&textureName];
			
			textureName = [[[path stringByDeletingLastPathComponent] stringByAppendingPathComponent:textureName] retain];
			
			NSLog(@"Loading Tex %@", textureName);
			
			materials[materialCount].textureMap = GetOpenGLTextureFromPath(textureName);
		}
	}
	materialCount++;
	
	return self;
}

- (MTLMaterial*) getMaterial:(NSString*)name
{
	int		i;
	
	for(i=0;i<materialCount;i++)
	{
		if([materials[i].name isEqualToString:name])
			return &(materials[i]);
	}
	
	return NULL;
}

@end
