//
//  ServiceNowa.m
//  Afficheur
//
//  Created by kichi on 08/10/06.
//  Copyright 2008 Katsuhiko Ichinose. All rights reserved.
//

#import "ServiceNowa.h"
#import "AfficheurController.h"
#import "AfficheurPreferences.h"
#import "AfficheurTimeline.h"
#import "AfficheurGrowl.h"
#import "NSStringOgreKit.h"
#import <OgreKit/OgreKit.h>

@implementation ServiceNowa

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

- (void)dealloc
{
	[super dealloc];
}

- (id)init:(NSString *)service
WithController:(AfficheurController *)controller
preferences:(AfficheurPreferences *)preferences
{
	self = [super init:service
		WithController:controller
		   preferences:preferences];
	if (self)
	{
	}
	return self;
}

- (BOOL)checkRetrieveTimeline:(NSDate *)now
{
	return [self checkRetrieve:now
					  withDate:_dateTimeline
					  interval:[_preferences accountNowaIntervalTimeline]];
}

- (void)post:(NSString *)status
   withReply:(NSString *)reply
{
	@synchronized(self)
	{
		@try
		{
			if (![reply isEqualToString:@""])
			{
				reply = [NSString stringWithFormat:@"&parent_id=%@", reply];
			}
			NSString *user = [_preferences accountNowaUser];
			NSString *pass = [_preferences accountNowaPass];
			NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:
								 @"api.nowa.jp", TwitterHost,
								 @"http://api.nowa.jp/statuses", TwitterURL,
								 user, TwitterUser,
								 pass, TwitterPass,
								 Afficheur, TwitterSource,
								 nil];
			status = [self stringFromEmojiNowa:status];
			EXPLOG(@"[%@(%@) post]\n%@", [self className], _service, status);
			[NSThread detachNewThreadSelector:@selector(performPost:)
									 toTarget:self
								   withObject:[[NSArray alloc] initWithObjects:status, dic, reply, nil]];
		}
		@catch (NSException *exception)
		{
			EXPLOG(@"[%@(%@) post] EXCEPTION\n%@: %@", [self className], _service, [exception name], [exception reason]);
		}
	}
}

- (NSImage *)imageWithUnichar:(unichar)unicode
{
	//LOG(@"[%@(%@) imageWithUnichar] %X", [self className], _service, unicode);
	return [NSImage imageNamed:[NSString stringWithFormat:@"nowa%04X", unicode]];
}

- (NSDictionary *)parse:(NSDictionary *)obj
			   withUser:(NSString *)user_id
				   kind:(int)kind
				  first:(BOOL)first
{
	if (![obj isKindOfClass:[NSDictionary class]])
	{
		return nil;
	}
	int loop = (kind >> 8) & 0xfffff;
	kind &= 0xff;
	NSDictionary *item = nil;
	@try
	{
		//LOG(@"[%@(%@) parse:%d] %@", [self className], _service, kind, obj);
		NSString *item_id = [NSString stringWithFormat:@"%@", [obj valueForKey:@"id"]];
		//LOG(@"[%@(%@) parse:%d] %@", [self className], _service, kind, item_id);
		NSDictionary *user = [obj valueForKey:@"user"];
		if (!user)
		{
			user = [obj valueForKey:@"sender"];
		}
		NSString *screen_name = [user valueForKey:@"screen_name"];
		NSString *user_name = [user valueForKey:@"name"];
		if (!user_name)
		{
			user_name = @"";
		}
		else if ([user_name isKindOfClass:[NSNull class]])
		{
			user_name = @"";
		}
		user_name = [self convertText:user_name];
		NSString *name = @"";
		if ((![user_name isEqualToString:@""]) &&(![user_name isEqualToString:screen_name]))
		{
			name = [NSString stringWithFormat:@" / %@", user_name];
		}
		NSString *user_profile = [user valueForKey:@"profile_image_url"];
		NSString *date = [obj valueForKey:@"created_at"];
		NSString *channel = @"";
		NSString *text = [obj valueForKey:@"text"];
		NSString *comment = @"";
		NSString *notify = _notify;
		NSString *kindStr = KindTimeline;
		NSString *inReplyUser = nil;
		if (!text || [text isKindOfClass:[NSNull class]])
		{
			text = @"";
		}
		text = [self stringFromEmoji:text];
		if (![screen_name isEqualToString:user_id] && [self hasKeyword:text])
		{
			notify = GrowlAfficheurKeywordsNotify;
			first = NO;
		}
		if (kind == kindReply)
		{
			notify = _notifyReply;
			kindStr = KindReply;
		}
		else if (kind == kindDM)
		{
			notify = _notifyDM;
			kindStr = KindDM;
		}
		id in_reply = [obj valueForKey:@"in_reply_to"];
		if (in_reply && ![in_reply isKindOfClass:[NSNull class]])
		{
			//LOG(@"[%@(%@) parse:%d]\nin_reply_to: %@", [self className], _service, kind, in_reply);
			NSString *reply_id = [in_reply valueForKey:@"id"];
			NSDictionary *reply = [self fetch:[NSString stringWithFormat:@"%@",
											   reply_id]
								  withService:_service];
			if (!reply)
			{
				NSString *user = [_preferences accountNowaUser];
				NSString *pass = [_preferences accountNowaPass];
				TwitterAPI *api = [[TwitterAPI alloc] initWithDictionary:
								   [NSDictionary dictionaryWithObjectsAndKeys:
									@"api.nowa.jp", TwitterHost,
									@"http://api.nowa.jp/statuses", TwitterURL,
									user, TwitterUser,
									pass, TwitterPass,
									nil]];
				if (api)
				{
					id status = [api show:reply_id];
					LOG(@"[%@(%@) parse:%d] reply: %d / %@", [self className], _service, kind, loop, reply_id);
					if (status && [status isKindOfClass:[NSDictionary class]] && ![status valueForKey:@"error"])
					{
						id reply_item = nil;
						if (loop < 50)
						{
							reply_item = [self parse:status
											withUser:user_id
												kind:kind | (((loop + 1) << 8) & 0xfffff00)
											   first:first];
						}
						if (reply_item)
						{
							if ([self addTimeline:reply_item])
							{
								[_controller queueingParsePhotoURL:reply_item];
							}
							reply = reply_item;
						}
						else
						{
							reply = [NSDictionary dictionaryWithObjectsAndKeys:
									 [[status valueForKey:@"user"] valueForKey:@"screen_name"], KeyUser,
									 [status valueForKey:@"text"], KeyText,
									 nil];
						}
					}
				}
			}
			if (reply)
			{
				inReplyUser = [reply valueForKey:KeyUser];
				comment = [NSString stringWithFormat:@"(on %@: %@)",
						   [reply valueForKey:KeyUser], [reply valueForKey:KeyText]];
				if ((kind == kindTimeline) || (kind == kindChannel))
				{
					if ([[reply valueForKey:KeyUser] isEqualToString:user_id])
					{
						notify = _notifyReply;
						first = NO;
					}
				}
			}
			else
			{
				inReplyUser = [[in_reply valueForKey:@"user"] valueForKey:@"screen_name"];
				comment = [NSString stringWithFormat:@"> %@", inReplyUser];
				if ((kind == kindTimeline) || (kind == kindChannel))
				{
					if ([inReplyUser isEqualToString:user_id])
					{
						notify = _notifyReply;
						first = NO;
					}
				}
			}
		}
		if ((kind == kindTimeline) || (kind == kindChannel))
		{
			if (([text lengthOfRegularExpression:[NSString stringWithFormat:@"@%@$", user_id]] > 0) ||
				([text lengthOfRegularExpression:[NSString stringWithFormat:@"@%@[^!-~]", user_id]] > 0))
			{
				notify = _notifyReply;
				first = NO;
			}
		}
		date = [NSString stringWithFormat:@"%@ +0900", date];
		if (kind == kindTimeline)
		{
			NSDate *created_at = [[NSDate dateWithNaturalLanguageString:date] retain];
			int i = 0;
			while (i < [_since count])
			{
				NSDate *since = [_since objectAtIndex:i];
				if ([since compare:created_at] != NSOrderedDescending)
				{
					break;
				}
				i++;
			}
			[_since insertObject:created_at atIndex:i];
		}
		if (kind == kindDM)
		{
			item_id = [NSString stringWithFormat:@"DM%@", item_id];
			user_profile = [NSString stringWithFormat:@"%@ %@", user_profile, Mail];
		}
		NSString *rid = [obj valueForKey:@"rid"];
		if ([text rangeOfRegularExpressionString:@"^(#\\S+) (.*)$" options:OgreMultilineOption].length > 0)
		{
			channel = [text replaceWithExpression:@"^(#\\S+) (.*)$" replace:@" \\1" options:OgreMultilineOption];
			text = [text replaceWithExpression:@"^(#\\S+) (.*)$" replace:@"\\2" options:OgreMultilineOption];
		}
		item = [self createItem:item_id
					   withUser:screen_name
						   name:name
						channel:channel
							rid:rid
						   text:text
						comment:comment
						 source:[obj valueForKey:@"source"]
					 created_at:[NSDate dateWithNaturalLanguageString:date]
				   user_profile:user_profile
						 notify:notify
						   kind:kindStr
					inReplyUser:inReplyUser
						  first:first];
	}
	@catch (NSException *exception)
	{
		EXPLOG(@"[%@(%@) parse:%d] EXCEPTION\n%@: %@", [self className], _service, kind, [exception name], [exception reason]);
	}
	return item;
}

- (void)retrieveTimeline
{
	//LOG(@"[%@(%@) retrieveTimeline]", [self className], _service);
	@synchronized(self)
	{
		if (_dateTimeline)
		{
			[self setupRetrieveDateTimeline:nil];
			@try
			{
				NSString *user = [_preferences accountNowaUser];
				NSString *pass = [_preferences accountNowaPass];
				NSDictionary *dic = [[NSDictionary alloc] initWithObjectsAndKeys:
									 @"api.nowa.jp", TwitterHost,
									 @"http://api.nowa.jp/statuses", TwitterURL,
									 user, TwitterUser,
									 pass, TwitterPass,
									 nil];
				[NSThread detachNewThreadSelector:@selector(performRetrieveTimeline:)
										 toTarget:self
									   withObject:dic];
			}
			@catch (NSException *exception)
			{
				EXPLOG(@"[%@(%@) retrieveTimeline] EXCEPTION\n%@: %@", [self className], _service, [exception name], [exception reason]);
			}
		}
	}
}

- (void)retrieveReplies
{
	//LOG(@"[%@(%@) retrieveTimeline]", [self className], _service);
}

- (void)retrieveDirectMessage
{
	//LOG(@"[%@(%@) retrieveDirectMessage]", [self className], _service);
}

- (void)doReply:(NSString *)item_id
	   withText:(BOOL)withText
{
	@try
	{
		//LOG(@"[%@(%@) doReply]\n%@", [self className], _service, item_id);
		id obj = [_controller fetchTimeline:item_id withService:_service];
		if (obj)
		{
			NSString *text = @"";
			if (withText)
			{
				text = [NSString stringWithFormat:@"@%@",
						[obj valueForKey:KeyUser]];
			}
			[_controller setReply:[self replyAttributedString:[NSString stringWithFormat:@"Reply to: %@%@",
														  [obj valueForKey:KeyText], [obj valueForKey:KeyComment]]]
					  withService:_service
						inReplyTo:item_id
							 text:text];
		}
	}
	@catch (NSException *exception)
	{
		EXPLOG(@"[%@(%@) doReply] EXCEPTION\n%@: %@", [self className], _service, [exception name], [exception reason]);
	}
}

- (void)favorite:(NSString *)item_id
{
}

- (void)permalink:(NSString *)item_id
{
	@try
	{
		id item = [self fetch:item_id withService:_service];
		if (item)
		{
			NSString *user = [item valueForKey:KeyUser];
			[self doOpenURL:[NSString stringWithFormat:@"http://%@.nowa.jp/status/%@",
							 user, [item_id replaceWithExpression:@"^.*?_(.*)$" replace:@"\\1"]]];
		}
	}
	@catch (NSException *exception)
	{
		EXPLOG(@"[%@(%@) permalink] EXCEPTION\n%@: %@", [self className], _service, [exception name], [exception reason]);
	}
}

@end
