//
//  SFSUser.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 "SFSUser.h"
#import "SFSException.h"
#import "SFSUserVariable.h"
#import "SmartFox2XClient.h"
#import "ISFSArray.h"
#import "Room.h"
#import "ArrayUtil.h"

@implementation SFSUser

@dynamic id;
@dynamic privilegeId;
@dynamic name;
@dynamic isItMe;
@dynamic properties;
@dynamic userManager;
@dynamic playerId;
@dynamic isPlayer;
@dynamic isSpectator;

@synthesize aoiEntryPoint = _aoiEntryPoint;


-(id)initWithId:(NSInteger)id name:(NSString *)name isItMe:(BOOL)isItMe {

	if((self = [super init])) {
	
		_id = id;
		_name = name;
		_isItMe = isItMe;
		_variables = [NSMutableDictionary dictionary];
		_properties = [NSMutableDictionary dictionary];
		_isModerator = NO;
		_playerIdByRoomId = [NSMutableDictionary dictionary];
	}
	return self;
}


+(id <User>)fromSFSArray:(id <ISFSArray>)sfsa room:(id <Room>)room {
    
	id <User> newUser = [[SFSUser alloc] initWithId:[sfsa getInt:0] name:[sfsa getUtfString:1] isItMe:NO];
	
	[newUser setPrivilegeId:[sfsa getShort:2]];
	
	if (room != nil) {
		[newUser setPlayerId:[sfsa getShort:3] room:room];
	}
	
	id <ISFSArray> uVars = [sfsa getSFSArray:4];
	
	for (int i = 0; i < [uVars size]; i++) {
		[newUser setVariable:[SFSUserVariable fromSFSArray:[uVars getSFSArray:i]]];
	}
	
	return newUser;
}

#pragma mark -
#pragma mark User protocol

-(NSInteger)id {
	return _id;
}

-(void)setId:(NSInteger)value {
	_id = value;
}

-(NSString *)name {
	return _name;
}

-(NSInteger)getPlayerId:(id<Room>)room {
	int pId = 0;
	
	if ([_playerIdByRoomId objectForKey:[NSNumber numberWithInt:(int)[room id]]] != nil) {
		pId = [(NSNumber *)[_playerIdByRoomId objectForKey:[NSNumber numberWithInt:(int)[room id]]] intValue];
	}
	
	return pId;
}

-(NSInteger)playerId {
	return [self getPlayerId:[[_userManager smartFox] lastJoinedRoom]];
}

-(BOOL)isPlayer {
	return [self playerId] > 0;
}

-(BOOL)isSpectator {
	return ![self isPlayer];
}



-(void)setPlayerId:(NSInteger)id_ room:(id<Room>)room {
	[_playerIdByRoomId setObject:[NSNumber numberWithInt:(int)id_] forKey:[NSNumber numberWithInt:(int)[room id]]];
}

-(void)removePlayerId:(id<Room>)room {
	[_playerIdByRoomId removeObjectForKey:[NSNumber numberWithInt:(int)[room id]]];
}

-(NSInteger)privilegeId {
	return _privilegeId;
}

-(void)setPrivilegeId:(NSInteger)value {
	_privilegeId = value;
}

-(id<IUserManager>)userManager {
	return _userManager;
}

-(void)setUserManager:(id<IUserManager>)value {
	if (_userManager != nil) {
		@throw [SFSException exceptionWithReason:[NSString stringWithFormat:@"Cannot re-assign the user manager. Already set. User: %ld", (long)_id]];
	}
	
	_userManager = value;
}

-(BOOL)isGuest {
	return _privilegeId == 0;
}

-(BOOL)isStandardUser {
	return _privilegeId == 1;
}

-(BOOL)isModerator {
	return _privilegeId == 2;
}

-(BOOL)isAdmin {
	return _privilegeId == 3;
}

-(BOOL)isPlayerInRoom:(id<Room>)room {
	return [(NSNumber *)[_playerIdByRoomId objectForKey:[NSNumber numberWithInt:(int)[room id]]] intValue] > 0; 
}

-(BOOL)isSpectatorInRoom:(id<Room>)room {
	return [(NSNumber *)[_playerIdByRoomId objectForKey:[NSNumber numberWithInt:(int)[room id]]] intValue] < 0;
}

-(BOOL)isJoinedInRoom:(id<Room>)room {
	return [room containsUser:self];
}

-(BOOL)isItMe {
	return _isItMe;
}

-(NSArray *)getVariables
{
    @synchronized (_variables)
    {
        return [ArrayUtil objToArray:_variables];
    }
}

-(id<UserVariable>)getVariable:(NSString *)varName
{
    @synchronized (_variables)
    {
        return [_variables objectForKey:varName];
    }
}

-(void)setVariable:(id<UserVariable>)userVariable
{
	if (userVariable != nil)
    {
        @synchronized (_variables)
        {
            if ([userVariable isNull])
                [_variables removeObjectForKey:[userVariable name]];
            
            else
                [_variables setObject:userVariable forKey:[userVariable name]];
        }
	}
}

-(void)setVariables:(NSArray *)userVariables
{
	for (id userVar in userVariables)
    {
		if ([userVar conformsToProtocol:@protocol(UserVariable)])
        {
			[self setVariable:userVar];
		}
	}
}

-(void)replaceVariables:(NSArray *)vars
{
	@synchronized (_variables)
	{
		[_variables removeAllObjects];
		[self setVariables:vars];
	}
}

-(BOOL)containsVariable:(NSString *)name
{
    @synchronized (_variables)
    {
        return ([_variables objectForKey:name] != nil);
    }
}

-(NSMutableDictionary *)properties
{
	return _properties;
}

-(void)setProperties:(NSMutableDictionary *)value
{
	_properties = value;
}

#pragma mark -

-(void)removeUserVariable:(NSString *)varName
{
    @synchronized (_variables)
    {
        [_variables removeObjectForKey:varName];
    }
}

-(NSString *)description {
	return [NSString stringWithFormat:@"[User: %@, Id: %ld, isMe: %@]", _name,(long) _id, (_isItMe) ? @"YES" : @"NO"];
}

@end
