package gmt.io.server;

import gmt.common.type.LogLevelType;
import gmt.common.type.MonitorUpdateType;
import gmt.common.util.GmtUtils;
import gmt.common.vo.MonitorInfoVO;
import gmt.common.vo.MsgObjVO;
import gmt.common.vo.NetStatVO;
import gmt.io.server.event.GmtServerEventListener;
import gmt.io.server.vo.ServerInfoVO;
import gmt.io.server.vo.ServiceClientVO;
import gmt.logger.GmtLogManager;
import gmt.protocol.event.GmtEncryptEventListener;
import gmt.protocol.event.GmtTestEventListener;
import ipworks.Connection;
import ipworks.ConnectionMap;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.LinkedBlockingQueue;

public class GmtServerManager {
	private String path;
	private Queue<MsgObjVO> recvQ;
	private GmtServerEventListener gmtServerEventListener;
	private GmtTestEventListener gmtTestEventListener;
	private GmtEncryptEventListener encryptListener;
	private GmtEncryptEventListener decryptListener;
	private HashMap<Integer, GmtServer> gmtservers;
	private Thread checkSocketThread;
	private LocalDateTime checkDt = LocalDateTime.now();
	private GmtLogManager logger;	

	public GmtServerManager(Queue<MsgObjVO> recvQ, String path, GmtServerEventListener gmtServerEventListener) {
//		GmtLogManager.setpath("");
		this.path = path;
		this.logger = GmtLogManager.getInstance();
		this.recvQ = recvQ;
		this.gmtServerEventListener = gmtServerEventListener;
		
		if (this.recvQ == null) {
			this.recvQ = new LinkedBlockingQueue<>(100000);
		}
		gmtservers = new HashMap<Integer, GmtServer>();

		checkSocketThread = new Thread(new Runnable() {
			Duration duration;

			@Override
			public void run() {
				while (true) {
					try {
						try {
							duration = Duration.between(checkDt, LocalDateTime.now());
							if (duration.getSeconds() >= 1) {
								checkSocket();
								checkDt = LocalDateTime.now();
							}

						} catch (Exception e) {
							logger.writeLevelLog("[ServerManager] checkSocketThread duration Error "+GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR, "AllLog");
						}

						Thread.sleep(100);
					} catch (InterruptedException e) {
						logger.writeLevelLog("[ServerManager] checkSocketThread Error"+GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR, "AllLog");
					}
				}
			}
		});
		checkSocketThread.start();
	};
	

	public void initializeServerFromXML() {
		if (path.equals("")) {
			path = System.getProperty("user.dir");	
		}
		File xmlFile = new File(path + "/cfg/server.xml");

		if (!xmlFile.exists()) {
			logger.writeLevelLog("[ServerManager] Load fail .. : "+ path+"\\cfg/server.xml", LogLevelType.LOG_ERROR, "AllLog");
			return;
		}
		
		logger.writeLevelLog("[ServerManager] Load file .. : "+ path+"\\cfg\\server.xml", LogLevelType.LOG_DEBUG, "AllLog");		

		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document doc = builder.parse(xmlFile);

			NodeList nodes = doc.getElementsByTagName("Server");

			for (int i = 0; i < nodes.getLength(); i++) {
				Node serverNode = nodes.item(i);

				int id = -1;
				int tag = 0;
				boolean use = false;
				int port = 0;
				String name = "";
				boolean lineMode = true;
				boolean chkRecvDt = false;
				int interval = 60;
				boolean doResend = false;
				boolean allowAny = true;
				boolean singleConn = true;

				for (Node child = serverNode.getFirstChild(); child != null; child = child.getNextSibling()) {
					if (child.getNodeType() != Node.ELEMENT_NODE) {
						continue;
					}

					try {
						Element chiledElement = (Element) child;

						if (chiledElement.getNodeName().equals("Connection")) {
							id = GmtUtils.strToIntDef(chiledElement.getAttribute("ID"), -1);
							tag = GmtUtils.strToIntDef(chiledElement.getAttribute("TAG"), -1);
							port = GmtUtils.strToIntDef(chiledElement.getAttribute("PORT"), 0);
							use = Boolean.parseBoolean(chiledElement.getAttribute("USE"));
							name = chiledElement.getAttribute("Name");
							allowAny = Boolean.parseBoolean(chiledElement.getAttribute("AllowAny"));

						}
						if (child.getNodeName().equals("Option")) {
							chkRecvDt = Boolean.parseBoolean(chiledElement.getAttribute("CheckRcv"));
							interval = GmtUtils.strToIntDef(chiledElement.getAttribute("Interval"), -1);
							lineMode = Boolean.parseBoolean(chiledElement.getAttribute("LineMode"));
							doResend = Boolean.parseBoolean(chiledElement.getAttribute("ReSend"));
							singleConn = Boolean.parseBoolean(chiledElement.getAttribute("SingleConn"));
						}
					} catch (Exception e) {
						logger.writeLevelLog(
								"[ServerManager] initializeServerFromXML Error " + GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR,
								"AllLog");
						continue;
					}

				}

				if (!use || id == -1) {
					continue;
				}

				GmtServer server = new GmtServer(recvQ, gmtServerEventListener);
				server.setId(id);
				server.setTag(tag);
				server.setName(name);
				server.setPort(port);
				server.setChkRecvDt(chkRecvDt);
				server.setInterval(interval);
				server.setLineMode(lineMode);
				server.setDoResend(doResend);
				server.setAllowAny(allowAny);
				server.setSingleConn(singleConn);
				server.setDecryptEventListener(decryptListener);
				server.setEncryptEventListener(encryptListener);

				if (!gmtservers.containsKey(server.getId())) {
					logger.writeLevelLog("[SERVER] ID : " + String.valueOf(server.getId()) + " PORT : "
							+ String.valueOf(server.getPort()), LogLevelType.LOG_INFO, "AllLog");
					gmtservers.put(server.getId(), server);
				}
			}
		} catch (Exception e) {
			logger.writeLevelLog("[ServerManager] initializeServerFromXML Error " + GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR,
					"AllLog");
		}
	};

	public void initAllowClientXML() {
		if (gmtservers.isEmpty()) {
			return;
		}
		if (path.equals("")) {
			path = System.getProperty("user.dir");
		}
		File xmlFile = new File(path + "/cfg/allowclient.xml");

		if (!xmlFile.exists()) {
			return;
		}

		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document doc = builder.parse(xmlFile);

			NodeList nodes = doc.getElementsByTagName("AllowClient");

			for (int i = 0; i < nodes.getLength(); i++) {
				Node serverNode = nodes.item(i);

				for (Node child = serverNode.getFirstChild(); child != null; child = child.getNextSibling()) {
					if (child.getNodeType() != Node.ELEMENT_NODE) {
						continue;
					}

					int id = -1;
					String ip = "";
					int serverPort = 0;
					String name = "";
					boolean allow = true;
					boolean SndStat = true;

					try {
						Element chiledElement = (Element) child;

						if (chiledElement.getNodeName().equals("Connection")) {
							id = GmtUtils.strToIntDef(chiledElement.getAttribute("ID"), -1);
							ip = chiledElement.getAttribute("IP");
							serverPort = GmtUtils.strToIntDef(chiledElement.getAttribute("ServerPort"), 0);
							name = chiledElement.getAttribute("Name");
							if (!Boolean.parseBoolean(chiledElement.getAttribute("RejectConn"))) {
								allow = true;
							} else {
								allow = false;
							}

						} else if (child.getNodeName().equals("Option")) {
							SndStat = Boolean.parseBoolean(chiledElement.getAttribute("SndStat"));
						} else if (child.getNodeName().equals("Reconnect")) {

						}
					} catch (Exception e) {
						logger.writeLevelLog("[ServerManager] initAllowClientXML Error " + GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR,
								"AllLog");
						continue;
					}

					for (GmtServer server : gmtservers.values()) {
						if (server == null) {
							return;
						}
						if (server.getPort() == serverPort) {
							if (allow == true) {
								server.setAllowList(name, ip, serverPort);
							} else {
								server.setRejectList(name, ip, serverPort);
							}
						}
					}
				}
			}
		} catch (Exception e) {
			logger.writeLevelLog("[ServerManager] initAllowClientXML Error " + GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR,
					"AllLog");
		}
	};

	public void checkSocket() {
		if (gmtservers.isEmpty()) {
			return;
		}
		for (GmtServer server : gmtservers.values()) {
			if (server == null) {
				return;
			}
			checkSocketSc(server);
			checkSocketScRcv(server);
		}

	}

	public void checkSocketSc(GmtServer server) {
		if (server == null) {
			return;
		}
		ConnectionMap connections = server.getConnections();
		if(connections == null) {
			return;
		}
		
		Duration duration;
		for (Connection connection : connections.values()) {
			if(connection == null || connection.getConnectionId() == null || connection.getConnectionId()=="") {
				continue;
			}
			String clientConnId = connection.getConnectionId();
			String SCKey = connection.getRemoteHost()+"|"+connection.getRemotePort()+"|"+connection.getConnectionId();
			
			LocalDateTime WBFromDT = server.getwouldBlockFromTime(SCKey);
			LocalDateTime WBToDT   = server.getwouldBlockToTime(SCKey);
			
			duration = Duration.between(WBFromDT, WBToDT);			
			if (duration.getSeconds() >= 5) {
				server.closeServiceClientOne(clientConnId);
				logger.writeLevelLog(
						"[SERVER : "+ String.valueOf(server.getPort()) +"][" + connection.getRemoteHost() + ":" + connection.getRemotePort() + "] Service Client Disconnect - WouldBLock occurred for 5 seconds.."
						, LogLevelType.LOG_INFO, "AllLog");
				continue;
			}
			
			int reSendCount     = server.getSCReSendQCnt(SCKey);
			NetStatVO netStatVO = server.getClientNetStatVO(SCKey);
			
			duration = Duration.between(netStatVO.getLastSendTime(), LocalDateTime.now());
			if ((duration.getSeconds() >= 10) && reSendCount > 0) {
				if (netStatVO.getRetryCount() < 3) {
					netStatVO.setRetryCount(netStatVO.getRetryCount() + 1);
					if (netStatVO.getRetryCount() == 1) {
						continue;
					}
					logger.writeLevelLog(
							"[" + connection.getRemoteHost() + ":" + connection.getRemotePort()
									+ "] Service Client Message ���� Retry " + netStatVO.getRetryCount(), LogLevelType.LOG_INFO,
							"AllLog");
					netStatVO.setLastSendTime(LocalDateTime.now());
				} else {
					logger.writeLevelLog(
							"[" + connection.getRemoteHost() + ":" + connection.getRemotePort()
									+ "] Service Client DisConnect - 30�� �� ���۽���..", LogLevelType.LOG_INFO,
							"AllLog");
					server.closeServiceClientOne(clientConnId);
				}
			}
			clientConnId = null;
			WBFromDT     = null;
			WBToDT       = null;
			SCKey        = null;
		}
		duration = null;
	}

	public void checkSocketScRcv(GmtServer server) {
		if (server == null) {
			return;
		}
		if (server.isChkRecvDt()) {
			Duration duration;
			ConnectionMap connections = server.getConnections();
			if(connections == null) {
				return;
			}
			for (Connection connection : connections.values()) {
				if(connection == null || connection.getConnectionId() == null || connection.getConnectionId()=="") {
					continue;
				}
				String clientConnId = connection.getConnectionId();
				String SCKey = connection.getRemoteHost()+"|"+connection.getRemotePort()+"|"+connection.getConnectionId();
				MonitorInfoVO monitorInfoVO = server.getMonitorInfoVO(SCKey);
				duration = Duration.between(monitorInfoVO.getLastRecvDT(), LocalDateTime.now());
				if ((duration.getSeconds() >= 60) && monitorInfoVO != null) {
					server.closeServiceClientOne(clientConnId);
					logger.writeLevelLog(
							"[" + connection.getRemoteHost() + ":" + connection.getRemotePort()
									+ "] Service Client DisConnect - 60�� ���� �޽����� ���� ���� ���߽��ϴ�..", LogLevelType.LOG_INFO,
							"AllLog");
				}
				SCKey = null;
				clientConnId = null;
				monitorInfoVO = null;
			}
			duration = null;
			connections = null;
		}
	}

	public void initMonitor() {
		if (gmtservers.isEmpty()) {
			return;
		}
		for (GmtServer server : gmtservers.values()) {
			if (server == null) {
				return;
			}

			ConnectionMap connections = server.getConnections();
			if(connections == null) {
				return;
			}
			for (Connection connection : connections.values()) {
				if(connection == null || connection.getConnectionId() == null || connection.getConnectionId()=="") {
					continue;
				}
				String SCKey = connection.getRemoteHost()+"|"+connection.getRemotePort()+"|"+connection.getConnectionId();
				server.updateMonitorInfo("".getBytes(), MonitorUpdateType.UPDATE);
				server.updateScMonitorInfo("".getBytes(), MonitorUpdateType.UPDATE, SCKey);
				SCKey = null;
			}
		}
	}

	public void startServer() {
		for (GmtServer server : gmtservers.values()) {
			try {
				server.Listen(server.getPort());
			} catch (Exception e) {
				logger.writeLevelLog("startServer : " + GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR, "AllLog");
				System.exit(0);
			}
		}
	};

	public void broadcastMsg(MsgObjVO vo) {
		try {
			for (GmtServer server : gmtservers.values()) {
				if (server != null) {
					String msgChk = new String(vo.getMsg());
					byte[] encMsg = "".getBytes();
							
					if (encryptListener != null) {
						if(!msgChk.equals("")) {
							encMsg = encryptListener.getByteArray(server.getId(), vo.getMsg());
							vo.setMsg(encMsg);
						}
					}
					
					for (Connection connection : server.getConnections().values()) {
						if (connection == null) {
							continue;
						}

						if (vo.getRecvIP().equals(connection.getRemoteHost())
								&& vo.getRecvPort() == connection.getRemotePort()) {
							continue;
						}
						MsgObjVO newVO = vo.getClone();
						if (gmtTestEventListener != null && !gmtTestEventListener.filterTesta(newVO, connection.getRemoteHost(), server.getPort())) {
							continue;
						}
						
						
						if (newVO != null) {
							newVO.setDestID(connection.getConnectionId());
							newVO.setDestIP(connection.getRemoteHost());
							newVO.setDestPort(connection.getRemotePort());
							
							server.addSendMsg(newVO);
						}
						newVO = null;
					}
				}
			}
		} catch (Exception e) {
			logger.writeLevelLog("[Server] broadcastServer Error " + GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR, "AllLog");
		}
	}
	
	public void broadcastMsg(String destIP, MsgObjVO vo) {
		try {
			for (GmtServer server : gmtservers.values()) {
				if (server != null) {
					String msgChk = new String(vo.getMsg());
					byte[] encMsg = "".getBytes();
							
					if (encryptListener != null) {
						if(!msgChk.equals("")) {
							encMsg = encryptListener.getByteArray(server.getId(), vo.getMsg());
							vo.setMsg(encMsg);
						}
					}
					
					for (Connection connection : server.getConnections().values()) {
						if (connection == null) {
							continue;
						}

						if (vo.getRecvIP().equals(connection.getRemoteHost())
								&& vo.getRecvPort() == connection.getRemotePort()) {
							continue;
						}
						
						// 지정한 목적지와 동일한 SC가 아니면 제외
						if (!connection.getRemoteHost().equals(destIP)) { 
							continue;
						}
						
						MsgObjVO newVO = vo.getClone();
						if (gmtTestEventListener != null && !gmtTestEventListener.filterTesta(newVO, connection.getRemoteHost(), server.getPort())) {
							continue;
						}
						
						
						if (newVO != null) {
							newVO.setDestID(connection.getConnectionId());
							newVO.setDestIP(connection.getRemoteHost());
							newVO.setDestPort(connection.getRemotePort());
							
							server.addSendMsg(newVO);
						}
						newVO = null;
					}
				}
			}
		} catch (Exception e) {
			logger.writeLevelLog("[Server] broadcastServer Error " + GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR, "AllLog");
		}		
	}

	public void broadcastServer(int serverId, MsgObjVO vo) {
		try {
			GmtServer server = gmtservers.get(serverId);
			if (server != null) {
				
				byte[] encMsg = "".getBytes();
				
				
				if (encryptListener != null) {
					encMsg = encryptListener.getByteArray(server.getId(), vo.getMsg());
					vo.setMsg(encMsg);
				}
				
				for (Connection connection : server.getConnections().values()) {
					if (connection == null) {
						continue;
					}

					if (vo.getRecvIP().equals(connection.getRemoteHost())
							&& vo.getRecvPort() == connection.getRemotePort()) {
						continue;
					}

					MsgObjVO newVO = vo.getClone();
					
					if (gmtTestEventListener != null && !gmtTestEventListener.filterTesta(newVO, connection.getRemoteHost(), server.getPort())) {
						continue;
					}

					if (newVO != null) {
						newVO.setDestID(connection.getConnectionId());
						newVO.setDestIP(connection.getRemoteHost());
						newVO.setDestPort(connection.getRemotePort());
						
						server.addSendMsg(newVO);
					}
					newVO = null;
				}
			}
			server = null;
		} catch (Exception e) {
			logger.writeLevelLog("[Server] broadcastServer Error " + GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR, "AllLog");
		}
	}

	public void sendServer(String targetIP, int serverId, MsgObjVO vo) {
		try {
			GmtServer server = gmtservers.get(serverId);
			if (server != null) {
				
				byte[] encMsg = "".getBytes();
				
				if (encryptListener != null) {
					encMsg = encryptListener.getByteArray(server.getId(), vo.getMsg());
					vo.setMsg(encMsg);
				}
				
				for (Connection connection : server.getConnections().values()) {
					if (connection == null) {
						continue;
					}

					if (vo.getRecvIP().equals(connection.getRemoteHost())
							&& vo.getRecvPort() == connection.getRemotePort()) {
						continue;
					}
					//gmtTestEventListener.filterTesta(vo, connection.getRemoteHost(), server.getPort()))

					if (connection.getRemoteHost().equals(targetIP)) {
						MsgObjVO newVO = vo.getClone();

						if (newVO != null) {
							newVO.setDestID(connection.getConnectionId());
							newVO.setDestIP(connection.getRemoteHost());
							newVO.setDestPort(connection.getRemotePort());
							
							server.addSendMsg(newVO);
						}
						newVO = null;
					}
				}
			}
			server = null;
		} catch (Exception e) {
			logger.writeLevelLog("[Server] sendServer Error " + GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR, "AllLog");
		}
	}

	public void sendServer(String targetIP, int targetPort, int serverId, MsgObjVO vo) {
		try {
			GmtServer server = gmtservers.get(serverId);
			if (server != null) {
				
				byte[] encMsg = "".getBytes();
				
				for (Connection connection : server.getConnections().values()) {
					if (connection == null) {
						continue;
					}

					if (vo.getRecvIP().equals(connection.getRemoteHost())
							&& vo.getRecvPort() == connection.getRemotePort()) {
						continue;
					}

					if (connection.getRemoteHost().equals(targetIP) && connection.getRemotePort() == targetPort) {
						MsgObjVO newVO = vo.getClone();

						if (newVO != null) {
							newVO.setDestID(connection.getConnectionId());
							newVO.setDestIP(connection.getRemoteHost());
							newVO.setDestPort(connection.getRemotePort());
							
						if (encryptListener != null) {
							encMsg = encryptListener.getByteArray(server.getId(), newVO.getMsg());
							newVO.setMsg(encMsg);
							}
							
							server.addSendMsg(newVO);
						}
						newVO = null;
					}
				}
			}
			server = null;
		} catch (Exception e) {
			logger.writeLevelLog("[Server] sendServer Error " + GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR, "AllLog");
		}
	}

	public void broadcastServerExceptSC(String exceptIP, int serverId, MsgObjVO vo) {
		try {
			GmtServer server = gmtservers.get(serverId);
			if (server != null) {
				
				byte[] encMsg = "".getBytes();
				
				for (Connection connection : server.getConnections().values()) {
					if (connection == null) {
						continue;
					}

					if (vo.getRecvIP().equals(connection.getRemoteHost())
							&& vo.getRecvPort() == connection.getRemotePort()) {
						continue;
					}
					

//					if (!connection.getRemoteHost().equals(exceptIP)) {
					
					if (!exceptIP.contains(connection.getRemoteHost())) {
						
						MsgObjVO newVO = vo.getClone();
						if (gmtTestEventListener != null && !gmtTestEventListener.filterTesta(newVO, connection.getRemoteHost(), server.getPort())) {
							continue;
						}

						if (newVO != null) {
							newVO.setDestID(connection.getConnectionId());
							newVO.setDestIP(connection.getRemoteHost());
							newVO.setDestPort(connection.getRemotePort());
							
							if (encryptListener != null) {
								encMsg = encryptListener.getByteArray(server.getId(), newVO.getMsg());
								newVO.setMsg(encMsg);
							}
							
							server.addSendMsg(newVO);
						}
						newVO = null;
					}
				}
			}
			server = null;
		} catch (Exception e) {
			logger.writeLevelLog("[Server] broadcastServerExceptSC Error " + GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR,
					"AllLog");
		}
	}

	public int getServiceClientCount() {
		int count = 0;

		for (GmtServer server : gmtservers.values()) {
			count = count + server.getConnectionsCount();
		}

		return count;
	}

	public String getMsgBuffer(int serverPort, String SCKey) {
		GmtServer server = gmtservers.get(serverPort);
		if (server != null) {
			return server.getServerMsgBuffer(SCKey);
		} else {
			return "";
		}
	}

	public boolean setMsgBuffer(int serverPort, String SCKey, String msgBuffer) {
		boolean result = false;
		GmtServer server = gmtservers.get(serverPort);
		if (server != null) {
			server.setServerMsgBuffer(SCKey, msgBuffer);
			result = true;
		}
		return result;
	}

	public void setSCUserInfo(int serverId, String SCKey, String userInfo) {
		try {
			GmtServer server = gmtservers.get(serverId);
			if (server != null) {
				server.setServiceClientUserInfo(serverId, SCKey, userInfo);
			}
			server = null;
		} catch (Exception e) {
			logger.writeLevelLog("[ServerManager] UserInfo setter Error "+GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR, "AllLog");
		}
	}

	public int getSendQCount(int serverId) {
		int result = 0;
		try {
			GmtServer server = gmtservers.get(serverId);
			if (server != null) {
				result = server.getServerSendQCount();
			}
			server = null;
		} catch (Exception e) {
			logger.writeLevelLog("[ServerManager] SendQCount getter Error "+GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR, "AllLog");
		}
		return result;
	}

	public boolean getServerMonitorInfo(int serverId, ServerInfoVO serverInfoVO) {
		boolean result = false;
		try {
			if (serverInfoVO == null) {
				return result;
			}
			GmtServer server = gmtservers.get(serverId);
			if (server == null) {
				return result;
			}
			serverInfoVO.setId(server.getId());
			serverInfoVO.setTag(server.getTag());
			serverInfoVO.setPort(server.getPort());
			serverInfoVO.setName(server.getName());
			serverInfoVO.setMonitorInfo(server.getServerMonitorInfoVO());
			serverInfoVO.setSndQcount(server.getServerSendQCount());
			/* serverInfoVO.setMaxSndQCount(maxSndQCount); */
			serverInfoVO.setServiceClientCount(server.getConnectionsCount());
			serverInfoVO.setUseFlag(server.isUse());
			result = true;
			server = null;
		} catch (Exception e) {
			logger.writeLevelLog("[ServerManager] TargetServerMonitorInfo getter Error"+GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR, "AllLog");
			return result;
		}
		return result;
	}

	public boolean getServerMonitorInfo(boolean init, CopyOnWriteArrayList<ServerInfoVO> serverInfoList) {
		boolean result = false;
		if (serverInfoList == null) {
			return result;
		}
		try {
			serverInfoList.clear();
			for (GmtServer server : gmtservers.values()) {
				if (server == null) {
					return result;
				}
				ServerInfoVO tempServerInfoVO = new ServerInfoVO();
				tempServerInfoVO.setId(server.getId());
				tempServerInfoVO.setTag(server.getTag());
				tempServerInfoVO.setPort(server.getPort());
				tempServerInfoVO.setName(server.getName());
				tempServerInfoVO.setMonitorInfo(server.getServerMonitorInfoVO());
				tempServerInfoVO.setSndQcount(server.getServerSendQCount());
				/* tempserverInfoVO.setMaxSndQCount(maxSndQCount); */
				tempServerInfoVO.setServiceClientCount(server.getConnectionsCount());
				tempServerInfoVO.setUseFlag(server.isUse());
				serverInfoList.add(tempServerInfoVO);
				tempServerInfoVO = null;
			}
			result = true;
		} catch (Exception e) {
			logger.writeLevelLog("[ServerManager] AllServerMonitorInfo"+GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR, "AllLog");
		}
		return result;
	}

	public boolean getSCMonitorInfo(boolean init, ConcurrentHashMap<String, ServiceClientVO> serviceClientList) {
		boolean result = false;
		if (serviceClientList == null) {
			return result;
		}
		try {
			serviceClientList.clear();
			for (GmtServer server : gmtservers.values()) {
				if (server != null) {
					for (Connection connection : server.getConnections().values()) {
						if(connection == null || connection.getConnectionId() == null || connection.getConnectionId()=="") {
							continue;
						}
						String SCKey = connection.getRemoteHost()+"|"+connection.getRemotePort()+"|"+connection.getConnectionId();
						ServiceClientVO tempServiceClientInfoVO = new ServiceClientVO();
						tempServiceClientInfoVO = server.getServiceClientInfo(SCKey);
						serviceClientList.put(SCKey, tempServiceClientInfoVO);
						tempServiceClientInfoVO = null;
						SCKey = null;
					}
				}
			}
			result = true;
		} catch (Exception e) {
			logger.writeLevelLog("[ServerManager] ServiceClientMonitorInfo getter Error "+GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR, "AllLog");
		}
		return result;
	}

	public int getServerPort(int serverId) {
		GmtServer server = gmtservers.get(serverId);
		return server.getPort();
	}
	
	public void closeServiceClient(int serverPort, String serviceClientIP, int serviceClientPort) {
		try {
			for(GmtServer server : gmtservers.values()) {
				if(server.getPort() == serverPort) {
					if(serviceClientPort == -1) {
						server.closeServiceClient(serviceClientIP);
					}else {
						server.closeServiceClient(serviceClientIP, serviceClientPort);
					}
					break;
				}
			}
		} catch (Exception e) {
			logger.writeLevelLog("[ServerManager] closeServiceClient Error "+GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR, "AllLog");
		}
	}
	
	public void closeAllServiceClient(int serverPort) {
		try {
			for(GmtServer server : gmtservers.values()) {
				if (server != null) {
					for (Connection connection : server.getConnections().values()) {
							server.closeServiceClient(connection.getRemoteHost());
					}
				}
			}
		} catch (Exception e) {
			logger.writeLevelLog("[ServerManager] closeServiceClient Error "+GmtUtils.getStatckTrace(e), LogLevelType.LOG_ERROR, "AllLog");
		}
	}
	
	public void setFilteringListener(GmtTestEventListener listener) {
		if (listener != null) {
			this.gmtTestEventListener = listener;
		}
	}
	
	public void setEncryptListener(GmtEncryptEventListener encryptListener) {
		this.encryptListener = encryptListener;
	}
	
	public void setDecryptListener(GmtEncryptEventListener decryptListener) {
		this.decryptListener = decryptListener;
	}
	
	public Boolean getServerLineMode(int id) {
		GmtServer server = this.gmtservers.get(id);		
		if (server == null) {
			return null;
		}
		
		return server.isLineMode();
	}
}
