//
//  FriendFeedAPI.m
//  Afficheur
//
//  Created by kichi on 10/01/03.
//  Copyright 2010 Katsuhiko Ichinose. All rights reserved.
//

#import "FriendFeedAPI.h"
#import "NSStringOgreKit.h"
#import <OgreKit/OgreKit.h>
#import <openssl/hmac.h>

NSString *FriendFeedUser	= @"FriendFeedUser";
NSString *FriendFeedPass	= @"FriendFeedPass";
NSString *FriendFeedHost	= @"FriendFeedHost";
NSString *FriendFeedURL		= @"FriendFeedURL";
NSString *FriendFeedKey		= @"FriendFeedKey";
NSString *FriendFeedSecret	= @"FriendFeedSecret";


@implementation FriendFeedAPI

- (id)init
{
	self = [super init];
	if (self)
	{
		_keys = [[NSDictionary dictionaryWithObjectsAndKeys:
				  @"", FriendFeedUser,
				  @"", FriendFeedPass,
				  @"", FriendFeedKey,
				  @"", FriendFeedSecret,
				  @"", FriendFeedHost,
				  @"", FriendFeedURL,
				  nil] retain];
		_dic = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
				@"", FriendFeedUser,
				@"", FriendFeedPass,
				@"", FriendFeedKey,
				@"", FriendFeedSecret,
				@"friendfeed-api.com", FriendFeedHost,
				@"http://friendfeed-api.com/v2", FriendFeedURL,
				nil];
	}
	return self;
}

- (void)dealloc
{
	[_keys release];
	[_dic release];
	[super dealloc];
}

- (id)initWithDictionary:(NSDictionary *)dic
{
	self = [self init];
	if (self)
	{
		NSEnumerator *enumerator = [dic keyEnumerator];
		id key;
		while ((key = [enumerator nextObject])) {
			id val = [_keys valueForKey:key];
			if (val == nil)
			{
				EXPLOG(@"[%@ initWithDictionary] NoKey: %@", [self className], key);
			}
			else
			{
				id value = [dic valueForKey:key];
				[_dic setValue:value forKey:key];
				if ([key isEqualToString:FriendFeedKey])
				{
					[self setAccessToken:value];
				}
				else if ([key isEqualToString:FriendFeedSecret])
				{
					[self setAccessTokenSecret:value];
				}
			}
		}
	}
	return self;
}

- (NSString *)user
{
	return [_dic valueForKey:FriendFeedUser];
}

- (id)ia_access_token:(NSString *)url
{
	if (!_comsumer_key || !_comsumer_secret || !_request_token_path)
	{
		return nil;
	}
	NSDate *date = [NSDate date];
	NSString *host = [url replaceWithExpression:@"^.*(:?http|https)://(.*?)/.*$"
														replace:@"\\2"];
	NSString *realm = [url replaceWithExpression:@"^.*((:?http|https)://.*?/).*$"
														 replace:@"\\1"];
	LOG2(@"[%@ ia_access_token]\n%@\n%@\n%@", [self className], url, host, realm);
	NSMutableDictionary *header = [NSMutableDictionary dictionaryWithObjectsAndKeys:
								   host, @"Host",
								   @"application/x-www-form-urlencoded", @"Content-Type",
								   [NSString stringWithFormat:
									@"OAuth ff_username=\"%@\", "\
									@"ff_password=\"%@\", "\
									@"realm=\"%@\", "\
									@"oauth_consumer_key=\"%@\", "\
									@"oauth_signature_method=\"HMAC-SHA1\", "\
									@"oauth_signature=\"@\", "\
									@"oauth_timestamp=\"%lu\", "\
									@"oauth_nonce=\"%lx\", "\
									@"oauth_version=\"1.0\"",
									[HTTP urlEncode:[_dic valueForKey:FriendFeedUser]
										  unescaped:@"-._~"
											escaped:@" !@#$^&*()`+=[]{}\\|;:'\"<>?,/"],
									[HTTP urlEncode:[_dic valueForKey:FriendFeedPass]
										  unescaped:@"-._~"
											escaped:@" !@#$^&*()`+=[]{}\\|;:'\"<>?,/"],
									realm,
									_comsumer_key,
									[self timestamp:date],
									[self nonce:date]
									], @"Authorization",
								   nil];
	header = [NSMutableDictionary dictionaryWithDictionary:
			  [self makeHeaderWithMethod:@"POST"
									 url:url
								  header:header
									body:@""
							 tokenSecret:nil]];
	LOG2(@"[%@ ia_access_token]\n%@", [self className], header);
	id auth = [self post:url
				  header:header
					body:@""];
	if ([auth isKindOfClass:[NSData class]])
	{
		auth = [[[NSString alloc] initWithData:auth encoding:NSUTF8StringEncoding] autorelease];
		LOG2(@"[%@ ia_access_token]\n%@", [self className], auth);
		if ([HTTP isHTML:auth] ||
			![auth lengthOfRegularExpression:@"oauth_token_secret"] ||
			![auth lengthOfRegularExpression:@"oauth_token"])
		{
			auth = nil;
		}
		else
		{
			NSArray *array = [auth componentsSeparatedByString:@"&"];
			if ([array count] < 2)
			{
				auth = nil;
			}
			else
			{
				NSEnumerator *enumerator = [array objectEnumerator];
				id object;
				while ((object = [enumerator nextObject]))
				{
					if ([object lengthOfRegularExpression:@"^oauth_token="])
					{
						[self setAccessToken:[object replaceWithExpression:@"^oauth_token=(.*)$"
																	replace:@"\\1"]];
					}
					else if ([object lengthOfRegularExpression:@"^oauth_token_secret="])
					{
						[self setAccessTokenSecret:[object replaceWithExpression:@"^oauth_token_secret=(.*)$"
																		  replace:@"\\1"]];
					}
				}
				LOG2(@"[%@ ia_access_token]\naccess_token=%@\naccess_token_secret=%@", [self className], _access_token, _access_token_secret);
			}
		}
	}
	return auth;
}

- (NSString *)encodeMessage:(NSString *)message
{
	return [HTTP urlEncode:message unescaped:nil escaped:@"&+=;"];
}

- (id)entry:(NSString *)status
{
	LOG2(@"[%@ entry]", [self className]);
	id result = [self postWithOAuth:[NSString stringWithFormat:@"%@/entry",
									 [_dic valueForKey:FriendFeedURL]]
							 header:[NSMutableDictionary dictionaryWithObjectsAndKeys:
									 [_dic valueForKey:FriendFeedHost], @"Host",
									 @"application/x-www-form-urlencoded", @"Content-Type",
									 nil]
							   body:[NSString stringWithFormat:
									 @"body=%@",
									 [self encodeMessage:status]]];
	return [self determineError:result WithJSON:YES];
}

- (id)entry:(NSString *)status
		 to:(NSString *)group
{
	LOG2(@"[%@ entry:to:]\n%@", [self className], group);
	id result = [self postWithOAuth:[NSString stringWithFormat:@"%@/entry",
									 [_dic valueForKey:FriendFeedURL]]
							 header:[NSMutableDictionary dictionaryWithObjectsAndKeys:
									 [_dic valueForKey:FriendFeedHost], @"Host",
									 @"application/x-www-form-urlencoded", @"Content-Type",
									 nil]
							   body:[NSString stringWithFormat:
									 @"body=%@&to=%@",
									 [self encodeMessage:status],
									 [self encodeMessage:group]]];
	return [self determineError:result WithJSON:YES];
}

- (id)comment:(NSString *)comment
	  withID:(NSString *)entry_id
{
	LOG2(@"[%@ comment]\n%@", [self className], entry_id);
	if (!entry_id || [entry_id isEqualToString:@""])
	{
		return [self entry:comment];
	}
	id result = [self postWithOAuth:[NSString stringWithFormat:@"%@/comment",
									 [_dic valueForKey:FriendFeedURL]]
							 header:[NSMutableDictionary dictionaryWithObjectsAndKeys:
									 [_dic valueForKey:FriendFeedHost], @"Host",
									 @"application/x-www-form-urlencoded", @"Content-Type",
									 nil]
							   body:[NSString stringWithFormat:
									 @"entry=%@&body=%@",
									 [self encodeMessage:entry_id],
									 [self encodeMessage:comment]]];
	return [self determineError:result WithJSON:YES];
}

- (id)like:(NSString *)entry_id
{
	LOG2(@"[%@ like]\n%@", [self className], entry_id);
	id result = [self postWithOAuth:[NSString stringWithFormat:@"%@/like",
									 [_dic valueForKey:FriendFeedURL]]
							 header:[NSMutableDictionary dictionaryWithObjectsAndKeys:
									 [_dic valueForKey:FriendFeedHost], @"Host",
									 @"application/x-www-form-urlencoded", @"Content-Type",
									 nil]
							   body:[NSString stringWithFormat:
									 @"entry=%@",
									 [self encodeMessage:entry_id]]];
	return [self determineError:result WithJSON:YES];
}

- (id)homeFeed
{
	id result =[self getWithOAuth:[NSString stringWithFormat:@"%@/feed/home",
								   [_dic valueForKey:FriendFeedURL]
								   ]
						   header:[NSMutableDictionary dictionaryWithObjectsAndKeys:
								   [_dic valueForKey:FriendFeedHost], @"Host",
								   nil]
							 body:@""];
	return [self determineError:result WithJSON:YES];
}

- (id)headHomeFeed
{
	id result =[self head:@"http://friendfeed.com/"
				   header:[NSMutableDictionary dictionaryWithObjectsAndKeys:
						   @"friendfeed.com", @"Host",
						   nil]
					 body:@""];
	return result;
}

@end
