#import "X24Connector.h"
#include <time.h>

#define X24CONNECTING NSLocalizedString(@"Connecting to TVN 24 ...",@"[1]")

#define X24MSGBEG @"Text=\""
#define X24MSGEND @"\""

@implementation X24Connector

- (id) init
{
	if (self = [super init])
	{
		messagesURL = [[NSUserDefaults standardUserDefaults] stringForKey: @"messagesURL"];
		[[NSNotificationCenter defaultCenter] addObserver: self
												 selector: @selector(allMessagesDisplayedNotificationHandler:) 
													 name: @"X24AllMessagesDisplayed" 
												   object: nil];
	}
	return self;
}

- (void) dealloc
{
	[[NSNotificationCenter defaultCenter] removeObserver: self];
	if (messagesURL)
		[messagesURL release];
	[super dealloc];
}

- (NSArray*) connectingMessage
{
	NSMutableArray* messages = [[NSMutableArray alloc] init];
	[messages addObject: [NSDictionary dictionaryWithObjectsAndKeys:
		[NSString stringWithFormat: X24CONNECTING, messagesURL], @"TEXT",
		@"DEFAULT", @"CATHEGORY",
		nil]];
	return [messages autorelease];
}


- (void) notifyAboutNewMessages: (id) newMessages
{
	[[NSNotificationCenter defaultCenter] postNotificationName: @"X24MessagesChanged"
														object: self
													  userInfo: [NSDictionary dictionaryWithObjectsAndKeys: newMessages, @"messages", nil]];
}


- (void) startDownloadingMessages
{
	unsigned int timestamp;
	NSString* timedMessagesURL;
	NSURL* url = [NSURL URLWithString: messagesURL];
	NSXMLDocument* allMessages = nil;
	NSArray* messages = nil;
	NSError* e;
	
	// new format introduced in 2008 (PasekTVN v. 1.8)
	// GET /NNNN,messages-v2.xml
	// where NNNN = time() / 100
	timestamp = ((unsigned int) time(NULL)) / 100;
	timedMessagesURL = [NSString stringWithFormat:messagesURL, timestamp];
	url = [NSURL URLWithString:timedMessagesURL];
		
	NS_DURING
		allMessages = [[NSXMLDocument alloc] initWithContentsOfURL: url
														   options: NSXMLNodeOptionsNone
															 error: &e];
	NS_HANDLER
		allMessages = nil;
	NS_ENDHANDLER
		
	if (allMessages == nil)
	{
		messages = [self connectingMessage];
	}
	else
	{
		messages = [self decodeXMLMessagesFromDocument: allMessages];
		if (messages == nil || [messages count] == 0)
		{
			messages = [self connectingMessage];
		}
		[allMessages release];
	}
	[messages retain];
	[self performSelectorOnMainThread: @selector(notifyAboutNewMessages:)
						   withObject: messages
						waitUntilDone: YES];
	[messages release];
}

- (void) downloadMessages
{
	[NSApplication detachDrawingThread: @selector(startDownloadingMessages)
							  toTarget: self
							withObject: nil];
}

- (void) allMessagesDisplayedNotificationHandler: (NSNotification*) n
{
	[self downloadMessages];
}

// The resulting array consists of two-item dictionaries:
// - under the @"TEXT" key there is the message content
// - under the @"CATHEGORY" key there is the cathegory indicator, which
//   affects the separator label (PILNE, KRAJ, SWIAT etc.)
- (NSArray*) decodeXMLMessagesFromDocument: (NSXMLDocument*) doc
{
	NSString* defaultCathegory = @"TVN24";	
	NSMutableArray* result = [NSMutableArray new];
	NSXMLNode* currentNode = [doc rootElement];
	NSXMLElement* currentElement;
	NSString* messageText;
	NSString* currentCathegory = defaultCathegory;
	
	while (currentNode != nil)
	{
		// cast to NSXMLElement if possible
		if ([currentNode isKindOfClass:[NSXMLElement class]])
			currentElement = (NSXMLElement*) currentNode;
		else
			currentElement = nil;

		// process a <ticker> node only if name="tvn24_scrolling"
		// if that's the case, it's an urgent message
		if ([[currentNode name] isEqualToString:@"ticker"] && currentElement &&
			[[[currentElement attributeForName:@"name"] stringValue] isEqualToString:@"tvn24_scrolling"])			
		{
			currentCathegory = @"PILNE";
		}
		
		// process an <item ...> node
		if ([[currentNode name] isEqualToString:@"item"] && currentElement)
		{			
			// check whether it's the category node
			if ([[[currentElement attributeForName:@"category"] stringValue] isEqualToString:@"true"])
			{
				currentCathegory = [currentElement stringValue];
				if (currentCathegory == nil)
					currentCathegory = defaultCathegory;
			}
			else
			{
				messageText = [currentElement stringValue];
				if (messageText != nil && ![messageText isEqualToString:@""])
				{
					[result addObject:
						[NSDictionary dictionaryWithObjectsAndKeys:
							messageText, @"TEXT",
							currentCathegory, @"CATHEGORY",
							nil
						]
					];
				}				
			}
		}
		currentNode = [currentNode nextNode];
	}	
	return [result autorelease];
}

@end
