package com.game;

import java.io.FileInputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;

import com.game.data.Player;
import com.game.data.Room;
import com.taurus.core.entity.ITObject;
import com.taurus.core.events.Event;
import com.taurus.core.events.IEventListener;
import com.taurus.core.plugin.redis.Redis;
import com.taurus.core.routes.Extension;
import com.taurus.core.routes.Routes;
import com.taurus.core.util.Logger;
import com.taurus.permanent.TPServer;
import com.taurus.permanent.core.TPEvents;
import com.taurus.permanent.data.Session;

/**
 * 
 * 
 */
public abstract class MainServer extends Extension implements IEventListener{

	public static MainServer	instance;

	private static final String	GMAE_CONFIG	= "config/game-config.xml";
	public GameSetting			gameSetting;
	
	@Override
	public void onStart() {
		instance = this;
		
		Global.logger = Logger.getLogger(getClass());
		try {
			loadConfig();
		} catch (Exception e) {
			Global.logger.error(e);
		}
		
		Global.init();

		TPServer.me().getEventManager().addEventListener(TPEvents.EVENT_SESSION_DISCONNECT, this);

		Map<String, String> svr_info = new HashMap<>();
		svr_info.put("ip", gameSetting.host);
		svr_info.put("port", gameSetting.port + "");
		 svr_info.put("intranet", gameSetting.intranet);
		svr_info.put("conns", "0");
		String svr_key = "svr" +gameSetting.serverId;
		Global.gameId = gameSetting.gameId;
		Global.gameName = Redis.use("group1_db1").hget("game:" + Global.gameId, "name");
		Global.loggerDebug = gameSetting.loggerDebug;
		Redis.use().hmset(svr_key, svr_info);
		Redis.use().expire(svr_key, 60);
		TPServer.me().getTimerPool().scheduleAtFixedRate(new Runnable() {

			@Override
			public void run() {
				try {
					svr_info.put("conns", Global.sessionMgr.size() + "");
					Redis.use().hmset(svr_key, svr_info);
					Redis.use().expire(svr_key, 60);
				} catch (Exception e) {
					Global.logger.error(e);
				}
			}
		}, 30, 30, TimeUnit.SECONDS);

		Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {

			@Override
			public void run() {
				List<Player> list = Global.sessionMgr.getPlayerList();
				for (Player p : list) {
					Global.sessionMgr.deleteSession(p.sender);
				}
			}
		}));
	}

	public abstract Room newRoom(String roomid, Map<String, String> redis_room_map);

	public abstract Player newPlayer(int playerid, Room room, String session_id);
	
	/**
	 * 创建游戏控制器
	 * @return
	 */
	protected abstract GameController newController();
	
	
	/**
	 * 发送事件给单一客户端
	 * @param cmdName		事件协议号
	 * @param params		数据参数
	 * @param recipient		客户端session
	 */
	public void sendEvent(String cmdName, ITObject params, Session recipient) {
		TPServer.me().getController().sendEvent(cmdName, params, recipient);
	}

	/**
	 * 发送事件给客户端
	 * @param cmdName		事件协议号
	 * @param params		 数据参数
	 * @param recipients	 客户端session列表
	 */
	public void sendEvent(String cmdName, ITObject params, List<Session> recipients) {
		TPServer.me().getController().sendEvent(cmdName, params, recipients);
	}

	/**
	 * 动态响应客户端请示
	 * @param gid 				响应标识ID
	 * @param result			响应结果 0成功
	 * @param params 			数据参数
	 * @param recipient 		客户端session
	 */
	public void sendResponse(int gid, int result, ITObject params, Session recipient) {
		TPServer.me().getController().sendResponse(gid, result, params, recipient);
	}
	
	protected void loadConfig() throws Exception {
		FileInputStream is = new FileInputStream(GMAE_CONFIG);
		SAXBuilder builder = new SAXBuilder();
		Document document = builder.build(is);
		Element root = document.getRootElement(); 
		GameSetting config = new GameSetting();
		config.host = root.getChildTextTrim("host");
		config.port = Integer.parseInt(root.getChildTextTrim("port"));
		config.serverId = Integer.parseInt(root.getChildTextTrim("serverId"));
		config.gameId = Integer.parseInt(root.getChildTextTrim("gameId"));
		config.loggerDebug =Boolean.parseBoolean(root.getChildTextTrim("loggerDebug"));
		config.intranet = root.getChildTextTrim("intranet");
		this.gameSetting = config;
	}
	
	@Override
	public void handleEvent(Event event) {
		if (event.getName() == TPEvents.EVENT_SESSION_DISCONNECT) {
			Session session = (Session) event.getParameter(TPEvents.PARAM_SESSION);
			Global.sessionMgr.disconnect(session);
		}
	}
	



	@Override
	public void configRoute(Routes me) {
		me.setInterceptor(new GameInterceptor());
		Global.gameCtr = newController();
		me.add("",Global.gameCtr);
	}

	public static final class GameSetting {
		public String	host		= "127.0.0.1";
		public String  	intranet	= "127.0.0.1";
		public int		port		= 6379;
		public int		serverId	= 1;
		public int		gameId		= 1;
		public boolean	loggerDebug	= true;
	}
}
