package jp.wda.gpss.samples.games;

import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import jp.wda.gpss.GeneralSocklet;
import jp.wda.gpss.SocketProcessor;
import jp.wda.gpss.Socklet;

/**
 * <FONT SIZE=2><I><B>
 * [ OProject GPSS for FlashMX ] FlashMX用汎用ソケットサーバ Sockletサンプル
 * </B></I></FONT><BR>
 * 海戦ゲーム戦域管理用Socklet
 *
 * @author	amoi
 */
public class NavalBattleAreaAdministrator extends GeneralSocklet {
	private LinkedList areaList = new LinkedList();
	private Hashtable  areaInfo = new Hashtable();
	
	// オーヴァーライド /////////////////////////////////////////////////////////////////
	//                                                               Over Ride Methods //
	/////////////////////////////////////////////////////////////////////////////////////

	/* ***********************************************************************>> */;
	/**
	 * BasicChat Sockletを初期化するためのメソッド。<BR>
	 * ソケット待受けサーバの起動時に、1回だけ呼ばれます。<BR><BR>
	 * 
	 * このメソッドでは、入室管理用Sockletを起動します。<BR>
	 *
	 * @see jp.wda.gpss.GeneralSocklet#init(List)
	 */
	protected void init(List linkedSocklets) {
		ChatroomInfo info = new ChatroomInfo("横島海域");
		areaInfo.put("横島海域", info);
		areaList.add(info);
	
		info = new ChatroomInfo("縦島海域");
		areaInfo.put("縦島海域", info);
		areaList.add(info);
	}
	
	public int addToRoom(String room){
		ChatroomInfo info = null;
		if(!areaInfo.containsKey(room)){
			info = new ChatroomInfo(room);
			areaInfo.put(room, info);
			areaList.add(info);
		}else{
			info = (ChatroomInfo)areaInfo.get(room);
		}
		
		sendToAllClients("<area name=\"" + room + "\" users=\"" + (++info.members) + "\" />");
		return info.members;
	}
	public int removeFromRoom(String room){
		if(!areaInfo.containsKey(room)){ return -1; }
		
		ChatroomInfo info = (ChatroomInfo)areaInfo.get(room);
		
		sendToAllClients("<area name=\"" + room + "\" users=\"" + (--info.members) + "\" />");
		return info.members;
	}
	private class ChatroomInfo{
		ChatroomInfo(String name){
			this.name = name;
			this.members = 0;
		}
		private String name;
		private int members;
	}

	/* ***********************************************************************>> */;
	/**
	 * 接続用初期コマンド受信後、クライアントの検査を行うためにメソッド。<BR>
	 * このメソッドは、サーバが新しいクライアントからの接続を確認した時点で、
	 * そのクライアントを検査するために呼ばれます。<BR><BR>
	 * 
	 * このメソッドは<BR>
	 * 
	 * @param client 接続を試みているクライアント
	 * @return 検査後、即切断する場合は偽。
	 * 
	 * @see jp.wda.gpss.Socklet#checkConnection(jp.wda.gpss.SocketProcessor)
	 */
	public boolean checkConnection(SocketProcessor client) {
		client.send("+OK welcome");
		return true;
	}

	/* ***********************************************************************>> */;
	/**
	 * クライアント削除前に呼び出されるメソッド。<BR>
	 * 接続中のクライアントが切断され、このアプリケーションから除外される直前に呼ばれます。<BR><BR>
	 * 
	 * このメソッドは<BR>
	 *
	 * @param client これから削除されるクライアント
	 * 
	 * @see jp.wda.gpss.Socklet#preRemoveClient(jp.wda.gpss.SocketProcessor)
	 */
	public void preRemoveClient(SocketProcessor client) {

	}

	/* ***********************************************************************>> */;
	/**
	 * コマンドを処理するためのメソッド。<BR>
	 * 接続中のクライアントから、コマンドが送信されてきたときに呼ばれます。<BR><BR>
	 * 
	 * このメソッドは<BR>
	 *
	 * @param client コマンドを送信してきたクライアントソケット
	 * @param command 受信したコマンド
	 * @return コマンド実行に成功した場合は真、失敗した場合は偽
	 * 	偽を返すと直ちにクライアントソケットを終了します。
	 * 
	 * @see jp.wda.gpss.Socklet#doCommand(jp.wda.gpss.SocketProcessor, java.lang.String)
	 */
	public boolean doCommand(SocketProcessor client, String command) {
		Iterator it = areaList.iterator();
		while(it.hasNext()){
			ChatroomInfo area = (ChatroomInfo)it.next();
			client.send("<area name=\"" + area.name + "\" users=\"" + area.members + "\" />");
		}
		return true;
	}

	
	/* ***********************************************************************>> */;
	/**
	 * 他のSockletからのアクセスを許可するかどうかを確認します。
	 * 
	 * @param from アクセスを試みてきた、他のSocklet
	 * @return そのSockletからのアクセスを許可する場合は真
	 */
	public boolean allowAccessFromOtherSocklet(Socklet from){
		if(!(from instanceof NavalBattle)){ return false; }
		return this.getName().equals(from.getName() + NavalBattle.ADMIN_FOTTER);
	}
}
