package sfs2x.extensions.games.spacewar2.game.handlers.requests;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import com.smartfoxserver.v2.annotations.Instantiation;
import com.smartfoxserver.v2.annotations.MultiHandler;
import com.smartfoxserver.v2.api.ISFSApi;
import com.smartfoxserver.v2.entities.Room;
import com.smartfoxserver.v2.entities.User;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.entities.data.SFSObject;
import com.smartfoxserver.v2.entities.variables.SFSUserVariable;
import com.smartfoxserver.v2.entities.variables.UserVariable;
import com.smartfoxserver.v2.extensions.BaseClientRequestHandler;
import com.smartfoxserver.v2.extensions.SFSExtension;

import sfs2x.extensions.games.spacewar2.game.SW2RoomExtension;
import sfs2x.extensions.games.spacewar2.shared.util.Constants;

@Instantiation
@MultiHandler
public class InitRequestHandler extends BaseClientRequestHandler
{
	@Override
	public void handleClientRequest(User sender, ISFSObject params)
	{
		// Get the request id
		String requestId = params.getUtfString(SFSExtension.MULTIHANDLER_REQUEST_ID);
		
		// CLIENT READY TO PLAY 
		if (requestId.equals(Constants.REQ_INIT_READY))
			onUserReady(sender);
		
		// SHIP SELECTED BY PLAYER
		else if (requestId.equals(Constants.REQ_INIT_SHIP))
			onShipSelected(sender, params);
	}
	
	/**
	 * Checks if game should start.
	 * If the game is not yet started, checks if the minimum number of players is reached; if yes, sends the start countdown notification to all clients.
	 */
	private void onUserReady(User user)
	{
		SW2RoomExtension roomExt = (SW2RoomExtension) this.getParentExtension();
		ISFSApi sfsApi = roomExt.getApi();
		Room room = roomExt.getParentRoom();
		
		//----------------------------------------
		
		// Mark user as ready by means of User properties
		user.setProperty("ready", true);
		
		// Send level, starships and weapons configuration to client
		ISFSObject configuration = new SFSObject();
		configuration.putSFSObject(Constants.CONFIG_LEVEL, roomExt.getLevelCfg());
		configuration.putSFSObject(Constants.CONFIG_STARSHIPS, roomExt.getStarshipsCfg());
		configuration.putSFSObject(Constants.CONFIG_WEAPONS, roomExt.getWeaponsCfg());
		
		sfsApi.sendExtensionResponse(Constants.RESP_CONFIG, configuration, user, room, false);
		
		// Check if game is already started, as set in Room Variables
		boolean gameStarted = room.getVariable(Constants.ROOMVAR_GAME_STATE).getIntValue() == Constants.GAMESTATE_RUNNING;
		
		if (!gameStarted)
		{
			// Get reference to countdown task from Room Extension
			ScheduledFuture<?> countdownTask = roomExt.getCountdownTask();
			
			// Check if final countdown is already in progress
			if (countdownTask != null)
			{
				// Get remaining time
				int delay = (int) countdownTask.getDelay(TimeUnit.SECONDS);
				
				// Send countdown start notification to user
				ISFSObject resParams = new SFSObject();
				resParams.putInt("delay", delay);
				
				sfsApi.sendExtensionResponse(Constants.RESP_COUNTDOWN, resParams, user, room, false);
			}
			else
			{
				// Get game settings
				ISFSObject settings = roomExt.getGameCfg();
				
				// Retrieve minimum number of players to start the game from game settings
				int minPlayers = settings.getInt(Constants.SETTING_MIN_PLAYERS);
				
				// Get list of ready users
				List<User> readyUsers = roomExt.getReadyUsers();
				
				if (readyUsers.size() >= minPlayers)
				{
					// Start countdown
					roomExt.startCountdown();
					
					// Send countdown start notification to ready users
					ISFSObject resParams = new SFSObject();
					resParams.putInt("delay", settings.getInt(Constants.SETTING_GAME_START_SECS));
					
					sfsApi.sendExtensionResponse(Constants.RESP_COUNTDOWN, resParams, readyUsers, room, false);
				}
			}
		}
		else
		{
			// Nothing to do; the user will be added to the game as soon as they select the starship (see onShipSelected method below)
		}
	}
	
	/**
	 * Saves the selected starship model in User Variables.
	 * If the game is already started, adds user to the game.
	 */
	private void onShipSelected(User user, ISFSObject params)
	{
		SW2RoomExtension roomExt = (SW2RoomExtension) this.getParentExtension();
		ISFSApi sfsApi = roomExt.getApi();
		Room room = roomExt.getParentRoom();
		
		//----------------------------------------
		
		// Save selected starship model in User Variables
		UserVariable shipModelUV = new SFSUserVariable(Constants.USERVAR_SHIP_MODEL, params.getUtfString("model"));
		List<UserVariable> userVars = new ArrayList<UserVariable>();
		userVars.add(shipModelUV);
		
		sfsApi.setUserVariables(user, userVars);
		
		// Check if game is already started; if yes add user to the game
		boolean gameStarted = room.getVariable(Constants.ROOMVAR_GAME_STATE).getIntValue() == Constants.GAMESTATE_RUNNING;
		
		if (gameStarted)
		{
			// Send start notification to all ready clients
			sfsApi.sendExtensionResponse(Constants.RESP_START, null, user, room, false);
			
			// Add user to game
			roomExt.addStarship(user);
		}	
	}
}
