/*******************************************************************************************
 * 
 * TITLE: 		SFS2X Space Race
 * VERSION:		1.0
 * RELEASE:		2011-03-15
 * COPYRIGHT:	2011 gotoAndPlay() - http://www.smartfoxserver.com
 * DEVELOPER:	A51 Integrated - http://a51integrated.com
 * 
 * This file is part of SFS2X Space Race.
 * 
 * Contributers: Wayne Helman, Fabricio Medeiros, David Irons,
 * 				 Steve Schoger, Ryan Albrecht, Andy Rohan
 * 
 * SFS2X Space Race is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * included license for more details.
 *
 * You are not allowed to rent, lend, lease, license or distribute SFS2X Space Race or a
 * modified version of SFS2X Space Race to any other person or organization in any way.
 * 
 * For commercial licensing information, please contact gotoAndPlay().
 * 
 *******************************************************************************************/

package sfs2x.extensions.games.spacerace;

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

import sfs2x.extensions.games.spacerace.handlers.GamePlayEvents;
import sfs2x.extensions.games.spacerace.handlers.SpacecraftUpdate;

import com.smartfoxserver.v2.SmartFoxServer;
import com.smartfoxserver.v2.extensions.SFSExtension;
import com.smartfoxserver.v2.entities.Room;
import com.smartfoxserver.v2.entities.User;
import com.smartfoxserver.v2.entities.Zone;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.entities.data.SFSObject;
import com.smartfoxserver.v2.entities.variables.ReservedRoomVariables;


/**
 * SFS2X Space Race demo - Game room extension
 * 
 * @author A51 Integrated
 *
 */
public class SpaceRaceGameExtension extends SFSExtension
{
	public static final String VERSION 					= "1.0";
		
	public static final String CMD_SPACECRAFTUPDATE 	= "U";
	public static final String CMD_GAMEPLAYEVENTS		= "G";
	public static final String CMD_OFFTRACK	   			= "O";
	public static final String CMD_ADVANTAGE  			= "A";
	public static final String CMD_HEALTHCHECK 			= "H";
	public static final String PLAYER_NAME				= "pn";
	public static final String TIMESTAMP				= "T";
	public static final String PLAYER_STATUS			= "s";
	public static final String NUM_PLAYERS				= "n";
	
	public ISFSObject obj = new SFSObject();
	public long startTime = 0;
	
	SmartFoxServer sfs;
	ScheduledFuture<?> taskScheduler;
	List<User> userList;
	int UPDATE_FREQUENCY = 33;
	int DELAY = 0;
	long currentTime = 0;
	
	Date now;
	
	@Override
	public void init()
	{
		trace("SFS2XSpaceRaceGameExt Extension init. Version: " + VERSION);
						
		// Get an instance of the SFS taskScheduler to send Spacecraft position updates to clients
		sfs = SmartFoxServer.getInstance();
		taskScheduler = sfs.getTaskScheduler().scheduleAtFixedRate(new BroadcastTask(), DELAY, UPDATE_FREQUENCY, TimeUnit.MILLISECONDS);
		
		// Register Request handlers
		this.addRequestHandler(CMD_SPACECRAFTUPDATE, SpacecraftUpdate.class);
		this.addRequestHandler(CMD_GAMEPLAYEVENTS, GamePlayEvents.class);
	}

	private class BroadcastTask implements Runnable
	{
		public void run()
	    {		
			userList = getGameRoom().getUserList();
			
			// Only send extension responses when the race has begun
			if (obj.size() > 0 && (!getParentRoom().getVariable(ReservedRoomVariables.RV_GAME_STARTED).isNull()))
			{		    					
				// Add the offset from game creation to now to the object being broadcast
				now = new Date();
				currentTime = now.getTime() - startTime;
				obj.putLong(TIMESTAMP, currentTime);
				
				// Send object containing all users latest received positions to all users in game room using TCP
				send(SpaceRaceGameExtension.CMD_SPACECRAFTUPDATE, obj,
						userList, true);
				
				// Cancel taskScheduler when room is empty
				if (userList.isEmpty())
				{
					taskScheduler.cancel(true);        			
				}
			}   	
	    }
	}
	
	public Room getGameRoom()
	{
		return this.getParentRoom();
	}
	
	public Zone getZone()
	{
		return this.getParentZone();
	}

	@Override
	public void destroy() 
	{
		taskScheduler.cancel(true);
		super.destroy();
	}
	
}
