//  Copyright 2009-2010 Aurora Feint, Inc.
// 
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//  
//  	http://www.apache.org/licenses/LICENSE-2.0
//  	
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

#import "OFInviteService.h"
#import "OFService+Private.h"
#import "OFHttpNestedQueryStringWriter.h"
#import "OFReachability.h"
#import "OFInvite.h"
#import "OFInviteDefinition.h"
#import "OFPaginatedSeries.h"
#import "OpenFeint+UserOptions.h"
#import "OFSelectInviteTypeController.h"
#import "OFUser.h"
#import "OpenFeint+Private.h"
#import "OFInviteNotificationController.h"
#import "OFFramedNavigationController.h"
#import "OFControllerLoader.h"
#import "OFDeviceContact.h"
#import "UIButton+OpenFeint.h"
#import "NSInvocation+OpenFeint.h"
#import "OFInviteNotificationController.h"

OPENFEINT_DEFINE_SERVICE_INSTANCE(OFInviteService)

@implementation OFInviteService

OPENFEINT_DEFINE_SERVICE(OFInviteService);

- (void) populateKnownResources:(OFResourceNameMap*)namedResources
{
	namedResources->addResource([OFUser getResourceName], [OFUser class]);
	namedResources->addResource([OFInvite getResourceName], [OFInvite class]);
	namedResources->addResource([OFInviteDefinition getResourceName], [OFInviteDefinition class]);
}

+ (OFRequestHandle*)getDefaultInviteDefinitionForApplication:(const OFDelegate&)onSuccess onFailure:(const OFDelegate&)onFailure
{
	return [[self sharedInstance] 
	 getAction:@"invite_definitions/primary"
	 withParameters:nil
	 withSuccess:onSuccess
	 withFailure:onFailure
	 withRequestType:OFActionRequestSilent
	 withNotice:nil];
}

+ (OFRequestHandle*)getInviteDefinition:(NSString*)inviteIdentifier onSuccess:(const OFDelegate&)onSuccess onFailure:(const OFDelegate&)onFailure
{
  OFPointer<OFHttpNestedQueryStringWriter> params = new OFHttpNestedQueryStringWriter;
	
	return [[self sharedInstance] 
	 getAction:[NSString stringWithFormat:@"invite_definitions/%@.xml", inviteIdentifier]
	 withParameters:params
	 withSuccess:onSuccess
	 withFailure:onFailure
	 withRequestType:OFActionRequestSilent
	 withNotice:nil];
}

+ (OFRequestHandle*)sendInvite:(OFInviteDefinition*)inviteDefinition withMessage:(NSString*)userMessage toUsers:(NSArray*)users onSuccess:(const OFDelegate&)onSuccess onFailure:(const OFDelegate&)onFailure
{
	OFPointer<OFHttpNestedQueryStringWriter> params = new OFHttpNestedQueryStringWriter;
	params->io("key", inviteDefinition.resourceId); 
	params->io("invite[sender_message]", userMessage);
	
	for(OFResource* resource in users) 
	{
		if([resource isKindOfClass:[OFUser class]])
		{
			params->io("invite[receivers][]", resource.resourceId); 
		}
		else if([resource isKindOfClass:[OFDeviceContact class]])
		{
			OFDeviceContact* contact = (OFDeviceContact*)resource;
			if(contact.number && ![contact.number isEqualToString:@""])
			{
				params->io("invite[sms_receivers][]", contact.number);
			}
			else if(contact.email && ![contact.email isEqualToString:@""])
			{
				params->io("invite[email_receivers][]", contact.email);
			}
			
		}
	}
	
	return [[self sharedInstance] 
	 postAction:@"invites.xml"
	 withParameters:params
	 withSuccess:onSuccess
	 withFailure:onFailure
	 withRequestType:OFActionRequestSilent
	 withNotice:nil];
}

+ (void)getInvitesForUser:(OFUser*)user pageIndex:(unsigned int)pageIndex onSuccess:(const OFDelegate&)onSuccess onFailure:(const OFDelegate&)onFailure
{
	OFPointer<OFHttpNestedQueryStringWriter> params = new OFHttpNestedQueryStringWriter; 
	params->io("page", pageIndex); 
	NSString* markViewed = @"true";
	params->io("mark_viewed", markViewed);

	[[self sharedInstance] 
	 getAction:@"invites.xml"
	 withParameters:params
	 withSuccess:onSuccess
	 withFailure:onFailure
	 withRequestType:OFActionRequestSilent
	 withNotice:nil];
}

+ (void)ignoreInvite:(NSString*)inviteResourceId onSuccess:(const OFDelegate&)onSuccess onFailure:(const OFDelegate&)onFailure
{
	[[self sharedInstance] 
	 putAction:[NSString stringWithFormat:@"invites/%@/ignore", inviteResourceId]
	 withParameters:nil
	 withSuccess:onSuccess
	 withFailure:onFailure
	 withRequestType:OFActionRequestSilent
	 withNotice:nil];	
}

+ (bool)canReceiveCallbacksNow
{
	return true;
}
#ifdef OF_PREMIUM
+ (void)unfulfilledInvitesFetched:(OFPaginatedSeries*)allInvites
{
	BOOL senderNotified = NO;
	
	id<OFInviteDelegate> inviteDelegate = [OpenFeint getInviteDelegate];
	
	for (OFInvite* inv in allInvites)
	{
		if ([inv.senderUser.resourceId isEqualToString:[OpenFeint lastLoggedInUserId]])
		{
			if (inviteDelegate)
			{
				[inviteDelegate sentInvite:inv.inviteIdentifier withSenderParameter:inv.senderParameter wasAcceptedByFriendUser:inv.receiverUser];
				
				// Only show one sender notification!
				if (!senderNotified)
				{
					senderNotified = YES;

					NSString* notificationText = inv.senderNotification;
					
					if (![inviteDelegate respondsToSelector:@selector(showCustomScreenForSentInviteAcceptance:)] ||
						![inviteDelegate showCustomScreenForSentInviteAcceptance:notificationText])
					{
						[OFInviteNotificationController showInviteNotification:notificationText withUser:inv.receiverUser withHeaderText:[NSString stringWithFormat:OFLOCALSTRING(@"%@ accepted your invite!"), inv.receiverUser.name]];
					}
				}
			}
		}
		else if ([inv.receiverUser.resourceId isEqualToString:[OpenFeint lastLoggedInUserId]])
		{
			if (inviteDelegate)
			{
				[inviteDelegate acceptedInvite:inv.inviteIdentifier withReceiverParameter:inv.receiverParameter fromFriendUser:inv.senderUser];
				
				NSString* notificationText = inv.receiverNotification;
				
				if (![inviteDelegate respondsToSelector:@selector(showCustomScreenForSentInviteAcceptance:)] ||
					![inviteDelegate showCustomScreenForSentInviteAcceptance:notificationText])
				{
					[OFInviteNotificationController showInviteNotification:notificationText withUser:inv.senderUser withHeaderText:[NSString stringWithFormat:OFLOCALSTRING(@"Invite from %@ accepted!"), inv.senderUser.name]];
				}
				
				// The reciever only gets one bonus, so at this point, we can cash out.
				return;
			}
		}
	}
}

+ (void)checkUnfulfilledInvites
{
	[[self sharedInstance] 
	 getAction:@"invites/unfulfilled"
	 withParameters:nil
	 withSuccess:OFDelegate(self, @selector(unfulfilledInvitesFetched:))
	 withFailure:OFDelegate()
	 withRequestType:OFActionRequestSilent
	 withNotice:nil];
}
#endif

+ (void)displaySendInviteModal:(NSString*)inviteIdentifier
{
	OFSelectInviteTypeController* controller = [OFSelectInviteTypeController inviteTypeControllerWithInviteIdentifier:inviteIdentifier];
	[controller openAsModal];
}

@end
