//
//  XTHtmlTag.m
//  TadsTerp
//
//  Created by Rune Berg on 29/03/14.
//  Copyright (c) 2014 Rune Berg. All rights reserved.
//

#import "XTHtmlTag.h"
#import "XTLogger.h"
#import "XTConverter.h"
#import "XTOutputFormatterProtocol.h"
#import "XTStringUtils.h"


@implementation XTHtmlTag

static XTLogger* logger;
static XTConverter *converter;


+ (NSString *)name
{
	return @"OOPS! XTHtmlTag name not overridden";
}

+ (NSArray *)allowedAttributes
{
	return @[];
}

+ (BOOL)standalone
{
	return YES;
}

+ (BOOL)blockLevel
{
	return NO;
}

+ (BOOL)blockLevelSpacingBefore
{
	return NO;
}

+ (BOOL)blockLevelSpacingAfter
{
	return NO;
}

+ (BOOL)forT2
{
	return YES;
}

+ (BOOL)forT3
{
	return YES;
}

//TODO various methods should test for nil self.attributes

+ (void)initialize
{
	logger = [XTLogger loggerForClass:[XTHtmlTag class]];
		//TODO find concrete class?
	converter = [XTConverter converter];
}

- (id)init
{
    self = [super init];
    if (self) {
		_attributes = [NSMutableDictionary dictionary];
	}
	return self;
}

- (BOOL)hasAttribute:(NSString *)attributeName
{
	BOOL res = ([self attributeAsString:attributeName] != nil);
	return res;
}

- (BOOL)hasAttribute:(NSString *)attributeName withCaseInsensitiveValue:(NSString *)value
{
	BOOL res = NO;
	
	NSString *actualValue = [self attributeAsString:attributeName];
	if (actualValue != nil) {
		actualValue = [actualValue lowercaseString];
		value = [value lowercaseString];
		if ([actualValue isEqualToString:value]) {
			res = YES;
		}
	}
	
	return res;
}

- (NSString *)attributeAsString:(NSString *)attributeName
{
	NSString *attributeValue = self.attributes[[attributeName lowercaseString]];
	return attributeValue;
}

- (BOOL)attribute:(NSString *)attributeName asOptionalSign:(NSInteger*)sign andUint:(NSUInteger*)uint
{
	id attributeValue = self.attributes[[attributeName lowercaseString]];
		//TODO trim
	BOOL res = NO;
	if (attributeValue != nil && attributeValue != [NSNull null]) {
		NSString *attributeValueStr = attributeValue;
		if (attributeValueStr.length >= 1) {
			NSInteger tempSign = 0;
			unichar ch = [attributeValueStr characterAtIndex:0];
			if (ch == '-') {
				tempSign = -1;
			} else if (ch == '+') {
				tempSign = 1;
			}
			NSUInteger uintStartIndex = (tempSign == 0 ? 0 : 1);
			NSString *uintStr = [attributeValueStr substringFromIndex:uintStartIndex];
			NSUInteger tempUint;
			if ([converter toUInteger:uintStr uinteger:&tempUint]) {
				*sign = tempSign;
				*uint = tempUint;
				res = YES;
			}
		}
	}
	return res;
}

//TODO rewrite like above, to communicate error
//TODO use
- (NSUInteger)attributeAsUInt:(NSString *)attributeName
{
	NSUInteger res = 0;
	
	id attributeValue = self.attributes[[attributeName lowercaseString]];
	//TODO trim

	BOOL ok = YES;
	if (attributeValue != nil && attributeValue != [NSNull null]) {
		NSString *attributeValueNumPrefix = [XTStringUtils numericPrefix:attributeValue];
		if (! [converter toUInteger:attributeValueNumPrefix uinteger:&res]) {
			ok = NO;
		}
	}
	if (! ok) {
		[logger error:@"XTHtmlTag.attributeAsUInt failed for value \"%@\"", attributeValue];
		//TODO emit some kind of error to caller?
	}
	
	return res;
}

- (NSNumber *)attributeAsNumber:(NSString *)attributeName
{
	NSNumber *res = nil;
	
	NSString *attributeValue = [self trimmedAttributeValue:attributeName];

	if (attributeValue != nil) {
		NSInteger intVal;
		if ([converter toInteger:attributeValue integer:&intVal]) {
			res = [NSNumber numberWithInteger:intVal];
		} else {
			[logger error:@"attributeAsNumber failed for value \"%@\"", attributeValue];
		}
	}
	
	return res;
}

//TODO unit test
- (NSArray *)attributeAsCommaSeparatedStrings:(NSString *)attributeName
{
	NSMutableArray *res = [NSMutableArray array];
	
	NSString *attributeValue = self.attributes[[attributeName lowercaseString]];

	if (attributeValue != nil && attributeValue.length >= 1) {
		NSArray *rawStrings = [attributeValue componentsSeparatedByString:@","];
		for (NSString *rawS in rawStrings) {
			NSString *trimmedS = [XTStringUtils trimLeadingAndTrailingWhitespace:rawS];
			[res addObject:trimmedS];
		}
	}
	return res;
}

/*TODO keep?
- (NSInteger)attributeAsInt:(NSString *)attributeName
{
	NSInteger res = 0;
	
	id attributeValue = self.attributes[[attributeName lowercaseString]];
	//TODO trim
	
	BOOL ok = YES;
	if (attributeValue != nil && attributeValue != [NSNull null]) {
		if (! [converter toInteger:attributeValue integer:&res]) {
			ok = NO;
		}
	}
	if (! ok) {
		[logger error:@"attributeAsInt failed for value \"%@\"", attributeValue];
		//TODO emit some kind of error to caller
	}
	
	return res;
}*/

//TODO use!
- (NSString *)trimmedAttributeValue:(NSString *)attributeName
{
	NSString *res = nil;
	 
	id attributeValue = self.attributes[[attributeName lowercaseString]];

	if (attributeValue != nil && attributeValue != [NSNull null]) {
		res = [XTStringUtils trimLeadingAndTrailingWhitespace:(NSString *)attributeValue];
	}
	
	return res;
}

- (BOOL)isStandalone
{
	BOOL res = [[self class] standalone];
	return res;
}

- (BOOL)isBlockLevel
{
	BOOL res = [[self class] blockLevel];
	return res;
}

- (BOOL)needsBlockLevelSpacingBefore
{
	BOOL res = [[self class] blockLevelSpacingBefore];
	return res;
}

- (BOOL)needsBlockLevelSpacingAfter
{
	BOOL res = [[self class] blockLevelSpacingAfter];
	return res;
}

- (BOOL)isForT2
{
	BOOL res = [[self class] forT2];
	return res;
}

- (BOOL)isForT3
{
	BOOL res = [[self class] forT3];
	return res;
}

- (NSString *)debugString
{
	NSString *closingSlash = (self.closing ? @"/" : @"");
	NSMutableString *res = [NSMutableString stringWithFormat:@"<%@%@", closingSlash, [[self class] name]];
	//TODO make work:
	for (NSString *name in self.attributes.allKeys) {
		id value = self.attributes[name];
		if ([value isKindOfClass:[NSNull class]]) {
			[res appendFormat:@" %@", name];
		} else {
			[res appendFormat:@" %@=\"%@\"", name, (NSString *)value];
		}
	}
	[res appendString:@">"];
	return res;
}

@end
