package sfs.cluster.lobby.handlers.internal;

import it.gotoandplay.smartfoxserver.SmartFoxServer;
import it.gotoandplay.smartfoxserver.data.Room;
import it.gotoandplay.smartfoxserver.data.User;
import it.gotoandplay.smartfoxserver.events.InternalEventObject;
import it.gotoandplay.smartfoxserver.exceptions.ExtensionHelperException;
import it.gotoandplay.smartfoxserver.exceptions.LoginException;
import it.gotoandplay.smartfoxserver.extensions.AbstractExtension;
import it.gotoandplay.smartfoxserver.extensions.ExtensionHelper;

import java.nio.channels.SocketChannel;
import java.util.LinkedList;
import java.util.logging.Logger;

import org.json.JSONObject;

import sfs.cluster.lobby.ClusterGameServerExtension;
import sfs.cluster.lobby.data.RoomReservation;

/**
 * Handle login for Game nodes
 */
public class GameLoginHandler implements InternalHandler
{
	ClusterGameServerExtension parentExtension;
	Logger log;
	
	public GameLoginHandler(AbstractExtension parentExtension)
	{
		this.parentExtension = (ClusterGameServerExtension) parentExtension;
	    log = SmartFoxServer.log;
	}
	
	// Handle the event
	public void handleInternalEvent(InternalEventObject ieo) throws Exception
	{
		String name = ieo.getParam("nick");
		String pass = ieo.getParam("pass");
	    SocketChannel channel = (SocketChannel) ieo.getObject("chan");
	    
	    log.info("Handling user login: " + name);
	    
	    // If a valid name was provided we keep checking
	    if (name != null && !name.equals(""))
	    {
	    	// Let's see if the user has an active reservation
	    	RoomReservation reservation = parentExtension.getReservation(name);
	    	
	    	if (reservation != null && !reservation.isExpired())
	    	{
	    		try
	    		{
	    			// Login
	    			User player = ExtensionHelper.instance().canLogin(name, pass, channel, parentExtension.getOwnerZone());
	    			
	    			JSONObject jso = new JSONObject();
	    		    jso.put("_cmd", "login");
	    			jso.put("name", player.getName());
	    		    jso.put("id", player.getUserId());
	    		    jso.put("result", "OK");
	    		    
	    		    LinkedList recipients = new LinkedList();
	    		    recipients.add(channel);
	    		    
	    		    parentExtension.sendResponse(jso, -1, null, recipients);
	    		    
	    		    Room targetRoom = parentExtension.getCurrentZone().getRoom(reservation.getTargetRoomId());
	    			
	    			if (targetRoom != null)
	    			{
	    				/*
	    				 * Send full room list
	    				 * TODO:
	    				 * 	possible optimization, we simply send a room list with the room that the user will join
	    				 * 	all the other are unnecessary and occupy useless bandwidth;
	    				 * 
	    				 */
	    				ExtensionHelper.instance().sendRoomList(channel);
	    				
	    				// Set the owner to its creator (which is the first one that will join)
	    				if (targetRoom.properties.get("inited") == null)
	    				{
	    					targetRoom.setCreator(player.getChannel());
	    					targetRoom.properties.put("inited", "true");
	    					targetRoom.setGame();
	    					
	    					player.addCreatedRoom(targetRoom);
	    					
	    					System.out.println(">> Creator was set --> " + targetRoom.getCreator());
	    				}
	    				
	    				// Join user in the reserved room
	    				ExtensionHelper.instance().joinRoom(player, -1, targetRoom.getId(), false, "", false, true);
	    				
	    				log.info("User: " + name + " -> successfully logged in and joined.");
	    				
	    				// Remove reservation
	    				parentExtension.removeReservation(name);
	    			}
	    			
	    			else
	    			{
	    				log.warning("Could not find reserved room. ID: " + reservation.getTargetRoomId());
	    				return;
	    			}

	    		}
	    		catch (LoginException logError) 
	    		{
	    			log.warning("Could not login user with valid reservation. User: " + name + ", Reason: " + logError);
	    			
	    			JSONObject jso = new JSONObject();
	    		    jso.put("_cmd", "login");
	    			jso.put("err", logError.getMessage());
	    		    jso.put("result", "KO");
	    		    
	    		    LinkedList recipients = new LinkedList();
	    		    recipients.add(channel);
	    		    
	    		    parentExtension.sendResponse(jso, -1, null, recipients);
	    		}
	    		catch (ExtensionHelperException helperError)
	    		{
	    			helperError.printStackTrace();
	    		}
	    	}
	    	
	    	// Invalid or not found reservation
	    	else
		    {
		    	log.warning("Reservation not found or expired for user: " + name + " -> RESERVATION: " + reservation);
		    }
	    }
	}
}
