#import <ObjFW/ObjFW.h>
#import <ObjXMPP/ObjXMPP.h>

#import "PEPThread.h"

#define NS_PUBSUB @"http://jabber.org/protocol/pubsub"
#define NS_TUNE @"http://jabber.org/protocol/tune"

@implementation PEPThread: OFThread
- (void)dealloc
{
	[sock release];

	[super dealloc];
}

- (void)MPD_connect
{
	int64_t pause = 1;
	while(1) {
		@try {
			[sock release];
			sock = [[OFTCPSocket alloc] init];
			[sock connectToHost: @"localhost"
				       port: 6600];
			return;
		} @catch (id e) {
			of_log(@"Connection failed, retrying in %" PRIi64
					" seconds", pause);
			[OFThread sleepForTimeInterval: pause];
			if (pause < 120)
				pause *= 2;
			[e release];
		}
	}
}

- (OFMutableDictionary*)MPD_responseFromSocket: (OFTCPSocket*)sock
{
	OFString *answer;
	OFMutableDictionary *response = [OFMutableDictionary dictionary];
	while ((answer = [sock readLine]) && ![answer hasPrefix: @"OK"]) {
		size_t index;
		index = [answer indexOfFirstOccurrenceOfString: @":"];
		if (index == OF_INVALID_INDEX)
			continue;
		[response setObject: [answer substringFromIndex: index + 2
							toIndex: answer.length]
			     forKey: [answer substringFromIndex: 0
							toIndex: index]];
	}

	return response;
}

- (id)main
{
	[self MPD_connect];
	[self MPD_responseFromSocket: sock];
	while (1) {
		OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
		@try {
			OFMutableDictionary *response;
			OFString *answer;
			XMPPIQ *tuneIQ;
			OFXMLElement *pubsub, *publish, *item, *tune;

			tuneIQ = [XMPPIQ IQWithType: @"set"
						 ID: [object generateStanzaID]];
			pubsub = [OFXMLElement elementWithName: @"pubsub"
						     namespace: NS_PUBSUB];
			[tuneIQ addChild: pubsub];
			publish = [OFXMLElement elementWithName: @"publish"
						      namespace: NS_PUBSUB];
			[publish addAttributeWithName: @"node"
					  stringValue: NS_TUNE];
			[pubsub addChild: publish];
			item = [OFXMLElement elementWithName: @"item"
						   namespace: NS_PUBSUB];
			[publish addChild: item];
			tune = [OFXMLElement elementWithName: @"tune"
						   namespace: NS_TUNE];
			[item addChild: tune];
			[sock writeLine: @"status"];
			response = [self MPD_responseFromSocket: sock];
			if ([[response objectForKey: @"state"]
			    isEqual: @"play"]) {
				[sock writeLine: @"currentsong"];
				response = [self MPD_responseFromSocket: sock];
				if ((answer =
				    [response objectForKey: @"Artist"]))
					[tune addChild: [OFXMLElement
					    elementWithName: @"artist"
						  namespace: NS_TUNE
						stringValue: answer]];
				if ((answer = [response objectForKey: @"Time"]))
					[tune addChild: [OFXMLElement
					    elementWithName: @"length"
						  namespace: NS_TUNE
						stringValue: answer]];
				if ((answer =
				    [response objectForKey: @"Album"]))
					[tune addChild: [OFXMLElement
					    elementWithName: @"source"
						  namespace: NS_TUNE
						stringValue: answer]];
				if ((answer =
				    [response objectForKey: @"Title"]))
					[tune addChild: [OFXMLElement
					    elementWithName: @"title"
						  namespace: NS_TUNE
						stringValue: answer]];
				if ((answer =
				    [response objectForKey: @"Track"]))
					[tune addChild: [OFXMLElement
					    elementWithName: @"track"
						  namespace: NS_TUNE
						stringValue: answer]];
			}
			[object sendStanza: tuneIQ];
			[sock writeLine: @"idle player"];
			[self MPD_responseFromSocket: sock];
		} @catch (id e) {
			[self MPD_connect];
			[self MPD_responseFromSocket: sock];
			[e release];
		}
		[pool release];
	}

	return nil;
}
@end
