//
//  GenericMessageRequest.m
//  SFS2X
//
//  Original development by Infosfer Game Technologies Ltd. | http://www.infosfer.com.
//
//  Maintained and developed by A51 Integrated.
//  Copyright 2012 A51 Integrated | http://a51integrated.com. All rights reserved.
//

#import "SmartFox2XClient.h"
#import "GenericMessageRequest.h"
#import "GenericMessageType.h"
#import "MessageRecipientMode.h"
#import "User.h"
#import "Logger.h"
#import "SFSValidationException.h"
#import "SFSException.h"

NSString * const GenericMessageRequest_KEY_ROOM_ID = @"r";
NSString * const GenericMessageRequest_KEY_USER_ID = @"u";
NSString * const GenericMessageRequest_KEY_MESSAGE = @"m";
NSString * const GenericMessageRequest_KEY_MESSAGE_TYPE = @"t";
NSString * const GenericMessageRequest_KEY_RECIPIENT = @"rc";
NSString * const GenericMessageRequest_KEY_RECIPIENT_MODE = @"rm";
NSString * const GenericMessageRequest_KEY_XTRA_PARAMS = @"p";
NSString * const GenericMessageRequest_KEY_SENDER_DATA = @"sd";

@implementation GenericMessageRequest

@synthesize room = _room;
@synthesize user = _user;
@synthesize message = _message;
@synthesize params = _params;
@synthesize recipient = _recipient;
@synthesize log = _log;



-(id)init {
	if ((self = [super initWithId:BaseRequest_GenericMessage])) {
		self.log = [Logger getInstance];
		_type = -1;
		_sendMode = -1;
	}
	
	return self;
}

-(void)validatePublicMessage:(SmartFox2XClient *)sfs errors:(NSMutableArray *)errors
{
	if(_message == nil || [_message length] == 0)
		[errors addObject:@"Public message is empty!"];
	
    if (_room != nil && ![sfs.joinedRooms containsObject:_room])
		[errors addObject:[NSString stringWithFormat:@"You are not joined in the target Room: %@", _room]];
	
}

-(void)validatePrivateMessage:(SmartFox2XClient *)sfs errors:(NSMutableArray *)errors {
	if(_message == nil || [_message length] == 0) {
		[errors addObject:@"Private message is empty!"];
	}
	
	if ([(NSNumber *)_recipient intValue] < 0) {
		[errors addObject:[NSString stringWithFormat:@"Invalid recipient id: %@", _recipient]];
	}
	
	
}

-(void)validateObjectMessage:(SmartFox2XClient *)sfs errors:(NSMutableArray *)errors {
	if (_params == nil) {
		[errors addObject:@"Object message is null!"];
	}
}

-(void)validateBuddyMessage:(SmartFox2XClient *)sfs errors:(NSMutableArray *)errors {
	
	if (![sfs.buddyManager isInited]) {
		[errors addObject:@"BuddyList is not inited. Please send an InitBuddyRequest first."];
	}
	
	if ([sfs.buddyManager myOnlineState] == NO) {
		[errors addObject:@"Can't send messages while off-line"];
	}
	
	if (_message == nil || [_message length] == 0) {
		[errors addObject:@"Buddy message is empty!"];
	}
	
	NSInteger recipientId = [(NSNumber *)_recipient intValue];
	if (recipientId < 0) {
		[errors addObject:@"Recipient is not online or not in your buddy list"];
	}
	
}
-(void)validateSuperUserMessage:(SmartFox2XClient *)sfs errors:(NSMutableArray *)errors {
	
	if (_message == nil || [_message length] == 0) {
		[errors addObject:@"Moderator message is empty!"];
	}
	
	if (_sendMode == MessageRecipientMode_TO_USER) {
		if (![_recipient conformsToProtocol:@protocol(User)]) {
			[errors addObject:@"TO_USER expects a User object as recipient"];
		}
		
	}
	else if (_sendMode == MessageRecipientMode_TO_ROOM) {
		if (![_recipient conformsToProtocol:@protocol(Room)]) {
			[errors addObject:@"TO_ROOM expects a Room object as recipient"];
		}
		
	}
	else if (_sendMode == MessageRecipientMode_TO_GROUP) {
		if (![_recipient isKindOfClass:[NSString class]]) {
			[errors addObject:@"TO_GROUP expects a String object (the groupId) as recipient"];
		}
	}
	
	
}

-(void)executePublicMessage:(SmartFox2XClient *)sfs {

	if (_room == nil) {
		self.room = sfs.lastJoinedRoom;
	}
	
	if (_room == nil) {
		@throw [SFSException exceptionWithReason:@"User should be joined in a room in order to send a public message"];
	}
	
	[_sfso putInt:GenericMessageRequest_KEY_ROOM_ID value:[_room id]];
	[_sfso putInt:GenericMessageRequest_KEY_USER_ID value:[sfs.mySelf id]];
	[_sfso putUtfString:GenericMessageRequest_KEY_MESSAGE value:_message];
	
	if (_params != nil) {
		[_sfso putSFSObject:GenericMessageRequest_KEY_XTRA_PARAMS value:_params];
	}
	
}

-(void)executePrivateMessage:(SmartFox2XClient *)sfs {
	
	[_sfso putInt:GenericMessageRequest_KEY_RECIPIENT value:[(NSNumber *)_recipient intValue]];
	[_sfso putUtfString:GenericMessageRequest_KEY_MESSAGE value:_message];
	
	if (_params != nil) {
		[_sfso putSFSObject:GenericMessageRequest_KEY_XTRA_PARAMS value:_params];
	}
	
}

-(void)executeBuddyMessage:(SmartFox2XClient *)sfs {
	
	[_sfso putInt:GenericMessageRequest_KEY_RECIPIENT value:[(NSNumber *)_recipient intValue]];
	[_sfso putUtfString:GenericMessageRequest_KEY_MESSAGE value:_message];
	
	if (_params != nil) {
		[_sfso putSFSObject:GenericMessageRequest_KEY_XTRA_PARAMS value:_params];
	}
}

-(void)executeSuperUserMessage:(SmartFox2XClient *)sfs {
	[_sfso putUtfString:GenericMessageRequest_KEY_MESSAGE value:_message];
	
	if(_params != nil) {
		[_sfso putSFSObject:GenericMessageRequest_KEY_XTRA_PARAMS value:_params];
	}
	
	[_sfso putInt:GenericMessageRequest_KEY_RECIPIENT_MODE value:_sendMode];
	
	if(_sendMode == MessageRecipientMode_TO_USER) {
		[_sfso putInt:GenericMessageRequest_KEY_RECIPIENT value:[(id <User>)_recipient id]];
	}
	
	else if(_sendMode == MessageRecipientMode_TO_ROOM) {
		[_sfso putInt:GenericMessageRequest_KEY_RECIPIENT value:[(id <Room>)_recipient id]];
	}
	
	else if(_sendMode == MessageRecipientMode_TO_GROUP) {
		[_sfso putUtfString:GenericMessageRequest_KEY_RECIPIENT value:_recipient];
	}	
}


-(void)executeObjectMessage:(SmartFox2XClient *)sfs {
	if (_room == nil) {
		self.room = sfs.lastJoinedRoom;
	}
	
	NSMutableSet *recipients = [NSMutableSet set];
	
	if ([_recipient isKindOfClass:[NSArray class]]) {
		
		NSArray *potentialRecipients = (NSArray *) _recipient;
		
		if ([potentialRecipients count] > [_room capacity]) {
			@throw [[NSException alloc] initWithName:@"NSException" reason:[NSString stringWithFormat:@"The number of recipients is bigger than the target Room capacity: %ld", (long)[potentialRecipients count]] userInfo:nil];
		}
		
		for(id item in potentialRecipients) {
			if([item conformsToProtocol:@protocol(User)]) {
				[recipients addObject:[NSNumber numberWithInt:(int)[(id <User>)item id]]];      
			}
			else {
				[_log warn:[NSString stringWithFormat:@"Bad recipient in ObjectMessage recipient list: %@, expected type: User", NSStringFromClass([item class])]];
			}
		}
	}
	
	[_sfso putInt:GenericMessageRequest_KEY_ROOM_ID value:[_room id]];
	[_sfso putSFSObject:GenericMessageRequest_KEY_XTRA_PARAMS value:_params];
	
	if([recipients count] > 0) {
		[_sfso putIntArray:GenericMessageRequest_KEY_RECIPIENT value:[recipients allObjects]];
	}
}


-(void)validate:(SmartFox2XClient *)sfs {
	
	if(_type < 0) {
		@throw [SFSValidationException validationExceptionWithReason:@"PublicMessage request error" errors:[NSMutableArray arrayWithObjects:[NSString stringWithFormat:@"Unsupported message type: %ld", (long)_type], nil]];
	}
	
	NSMutableArray *errors = [NSMutableArray array];
	
	if (_type == GenericMessageType_PUBLIC_MSG) {
		[self validatePublicMessage:sfs errors:errors];
	}
	
	else if(_type == GenericMessageType_PRIVATE_MSG) {
		[self validatePrivateMessage:sfs errors:errors];
	}
	
	else if(_type == GenericMessageType_OBJECT_MSG) {
		[self validateObjectMessage:sfs errors:errors];
	}
	
	else if(_type == GenericMessageType_BUDDY_MSG) {
		[self validateBuddyMessage:sfs errors:errors];
	}
	
	else {
		[self validateSuperUserMessage:sfs errors:errors];
	}
	
	if ([errors count] > 0) {
		@throw [SFSValidationException validationExceptionWithReason:@"Request error - " errors:errors];
	}

	
}


-(void)execute:(SmartFox2XClient *)sfs{
	
	[_sfso putByte:GenericMessageRequest_KEY_MESSAGE_TYPE value:_type];
	
	if (_type == GenericMessageType_PUBLIC_MSG) {
		[self executePublicMessage:sfs];
	}
	
	else if (_type == GenericMessageType_PRIVATE_MSG) {
		[self executePrivateMessage:sfs];
	}
	
	else if(_type == GenericMessageType_OBJECT_MSG) {
		[self executeObjectMessage:sfs];
	}
	
	else if(_type == GenericMessageType_BUDDY_MSG) {
		[self executeBuddyMessage:sfs];
	}
	
	else {
		[self executeSuperUserMessage:sfs];
	}

		
}


@end
