//
//  UISpec+UISpecRunner.m
//  UISpecRunner
//
//  Created by Blake Watters on 7/15/10.
//  Copyright 2010 Two Toasters. All rights reserved.
//

#import "UISpec+UISpecRunner.h"
#import <objc/runtime.h>

@implementation UISpec (UISpecRunner)

+(BOOL)class:(Class)class conformsToProtocol:(Protocol *)protocol {
	while (class) {
		if (class_conformsToProtocol(class, protocol)) {
			return YES;
		}
		class = class_getSuperclass(class);
	}
	return NO;
}

+(NSArray*)specClassesConformingToProtocol:(Protocol *)protocol {
	NSMutableArray *array = [NSMutableArray array];
    int numClasses = objc_getClassList(NULL, 0);
    if (numClasses > 0) {
        Class *classes = malloc(sizeof(Class) * numClasses);
        (void) objc_getClassList (classes, numClasses);
        int i;
        for (i = 0; i < numClasses; i++) {
            Class c = classes[i];
			if ([self isASpec:c] && [self class:c conformsToProtocol:protocol]) {
				[array addObject:c];
			}
        }
        free(classes);
    }
	return array;
}

+(void)runSpecsConformingToProtocol:(Protocol *)protocol afterDelay:(NSTimeInterval)delay {
	NSArray* specClasses = [self specClassesConformingToProtocol:protocol];
	[self performSelector:@selector(runSpecClasses:) withObject:specClasses afterDelay:delay];
}

+(void)runSpecsFromEnvironmentAfterDelay:(int)seconds {
	char* protocolName = getenv("UISPEC_PROTOCOL");
	char* specName = getenv("UISPEC_SPEC");
	char* exampleName = getenv("UISPEC_EXAMPLE");
	if (protocolName) {
		Protocol* protocol = NSProtocolFromString([NSString stringWithUTF8String:protocolName]);
		NSLog(@"[UISpecRunner] Running Specs conforming to Protocol: %@", [NSString stringWithUTF8String:protocolName]);
		[UISpec runSpecsConformingToProtocol:protocol afterDelay:seconds];
	} else if (exampleName) {
		if (nil == specName) {
			[NSException raise:nil format:@"UISPEC_EXAMPLE cannot be specified without providing UISPEC_SPEC"];
		}
		NSLog(@"[UISpecRunner] Running Examples %s on Spec %s", exampleName, specName);
		[UISpec runSpec:[NSString stringWithUTF8String:specName] example:[NSString stringWithUTF8String:exampleName] afterDelay:seconds];
	} else if (specName) {
		NSLog(@"[UISpecRunner] Running Spec %s", specName);
		[UISpec runSpec:[NSString stringWithUTF8String:specName] afterDelay:seconds];
	} else {
		[UISpec runSpecsAfterDelay:seconds];
	}	
}

@end
