package com.eactive.eai.adapter.socket2.protocol.http.servlet;

import com.eactive.eai.adapter.AdapterManager;
import com.eactive.eai.adapter.AdapterVO;
import com.eactive.eai.adapter.socket2.common.Env;
import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
import com.eactive.eai.adapter.socket2.common.TimeUtil;
import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
import com.eactive.eai.adapter.socket2.protocol.http.HttpServlet;
import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
import com.eactive.eai.common.util.Logger;
import org.apache.mina.common.IoSession;
import org.json.simple.JSONArray;

import java.net.URLDecoder;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class AdaptersJsonServlet extends HttpServlet {
	static final SocketAdapterManager manager = SocketAdapterManager.getInstance();
    static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_HTTP");

	protected void doService(HttpRequest request, HttpResponse response) throws Exception {
		String filter = request.getContext();
    	filter = filter.substring(filter.indexOf('/')+1);
    	if ("adaptersJson".equals(filter)) {
    		filter = null;
    	}
    	
    	String result = "";
    	try {
	    	result = list(filter);
		} catch(Throwable e) {
			result = "<pre>" + ExceptionStackTrace.dump(e) + "</pre>";
		}
		
		if (!"".equals(request.getParameter("refresh"))) {
			response.appendBody("<meta http-equiv='refresh' content=" + request.getParameter("refresh") + "; url=" + request.getContext() + ">\n\n");
		}
		
    	response.setContentType("text/html;charset=utf-8;");
    	response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
		response.appendBody(result);
	}

	private String list(String filter) {
//		boolean verbose = false;		
		//StringBuffer sb = new StringBuffer();
		try{
			filter = URLDecoder.decode(filter,"UTF-8");
		}catch(Exception e){
			if(filter != null) filter = filter.trim();
		}
		ConcurrentHashMap adapterGroups = (ConcurrentHashMap) SocketAdapterManager.getInstance().getSocketAdapterGroups();
		List list = new ArrayList<HashMap>();
		String prevAdapterGroupName = "";
	    for (Enumeration e = adapterGroups.keys(); e.hasMoreElements();) {
	    	String adapterGroupName = (String) e.nextElement();    	
	    	ConcurrentHashMap adapters = (ConcurrentHashMap) adapterGroups.get(adapterGroupName);
	    	
		    for (Enumeration ee = adapters.elements() ; ee.hasMoreElements() ;) {
		    	ISocketAdapter adapter = (ISocketAdapter) ee.nextElement();
		    	if (filter != null && adapter.getContext().getAdapterName().toLowerCase().indexOf(filter.toLowerCase()) == -1
			    	&& adapter.getContext().getProtocol().toLowerCase().indexOf(filter.toLowerCase()) == -1
		    		&& String.valueOf(adapter.getContext().getPortNumber()).toLowerCase().indexOf(filter.toLowerCase()) == -1
		    		&& adapter.getContext().getDescription().indexOf(filter.toLowerCase()) == -1)
		    		continue;		    	
	    	
		    	HashMap<String,Object> row = new HashMap<String,Object>();
		    	row.put("adapterGroupName", adapterGroupName);
		    	row.put("adapterName", adapter.getContext().getAdapterName());
		    	row.put("state", adapter.getState().name());
		    	if (Env.isWindows()) {
		    		row.put("status", "");
		    	}else{
		    		row.put("status", getAdapterStatus(adapterGroupName, adapter.getContext().getAdapterName()));
		    		
		    	}
		    	row.put("uptime", TimeUtil.formatDate(adapter.getUptime().getTime()));
		    	if (adapter.getSessionPool() != null) {
		    		row.put("pool", adapter.getSessionPool().remaining() + "/" + (adapter.getSessionPool().peekSize()));
		    	}
		    	row.put("recv", adapter.getMessageRecv());
		    	row.put("send", adapter.getMessageSend());
		    	
		    	row.put("error", adapter.getRecentErrorCount());
		    	
		    	row.put("trace", adapter.getContext().getTraceLevel());
		    	

		    	StringBuffer sb = new StringBuffer();
		    	sb.append(adapter.getContext().getProtocol());
		    	sb.append(", " + adapter.getContext().getBoundUsage() );
		    	sb.append(", " + adapter.getContext().getSocketType() );
		    	if (adapter.getContext().isClient()) {
			    	sb.append(" (" + adapter.getContext().getLocalHostName() + ":" + adapter.getContext().getLocalPortNumber());
			    	sb.append("->");
			    	sb.append("/" + adapter.getContext().getHostName() + ":" + adapter.getContext().getPortNumber() + ")");
		    	} else {
		    		sb.append(" (" + adapter.getContext().getHostName() + ":" + adapter.getContext().getPortNumber());
			    	sb.append("<-)");
		    	}
		    	if(adapter.getContext().isSync()) {
		    		sb.append(", SYNC");
		    	} else {
		    		sb.append(", ASYN");
		    	}
		    	if ("Y".equals(adapter.getContext().getAckSupport())) {
		    		sb.append(", ACK");
		    	} else {
		    		sb.append(", NO_ACK");
		    	}
		    	if(adapter.getContext().isPermanent()) {
		    		sb.append(", PERMANENT");
		    	} else {
		    		sb.append(", NON_PERM");
		    	}
		    	if(adapter.getContext().isBlocking()) {
		    		sb.append(", BIO");
		    	} else {
		    		sb.append(", NIO");
		    	}
		    	sb.append(", max_conn:" + (adapter.getContext().getCloseExistingConnection() ? "-" : "") + adapter.getContext().getMaxConnection());
		    	sb.append(", limit_per_ip:" + adapter.getContext().getConnLimitPerIp());
		    	sb.append(", max_thread:" + adapter.getContext().getMaxThread());

//		    	switch(adapter.getContext().getTraceLevel()) {
//		    	case 0:
//		    		sb.append(", 0(DEFAULT)");
//		    		break;
//		    	case 1:
//		    		sb.append(", 1(INFO)");
//		    		break;
//		    	case 2:
//		    		sb.append(", 2(DEBUG)");
//		    		break;
//		    	case 3:
//		    		sb.append(", 3(TRACE)");
//		    		break;
//		    	}
		    	
		    	if (adapter.getContext().isPollingUse()) {
			    		sb.append("\n(");
				    	sb.append("POLLING");
				    	sb.append(", " + adapter.getContext().getPollingRole());
				    	if (adapter.getContext().isPollingOneway()) {
				    		sb.append(", oneway");
				    	}
				    	sb.append(", " + adapter.getContext().getPollingTimeout());
//				    	sb.append(", " + adapter.getContext().getPollingRequest());
//				    	sb.append(", " + adapter.getContext().getPollingRequestPattern());
//				    	sb.append(", " + adapter.getContext().getPollingReplacement());
//				    	sb.append(", " + adapter.getContext().getPollingResponsePattern());
			    		sb.append(")");
			    }
		    	//KSH
		    	if (adapter.getContext().isInitMsgUse()) {
		    		sb.append("\n(");
			    	sb.append("INIT_MSG");
			    	sb.append(", " + adapter.getContext().getInitMsgRole());
					sb.append(")");
		    	}
		    	
		    	if ("FIXED_LENGTH_HEADER".equals(adapter.getContext().getProtocol()) 
                 || "UDP_FIXED_LENGTH_HEADER".equals(adapter.getContext().getProtocol()) 
                 || "VARIABLE_LENGTH_HEADER".equals(adapter.getContext().getProtocol())  //20130719 KSH
                 || "EGSEED".equals(adapter.getContext().getProtocol())
	    		 || "TCSEED".equals(adapter.getContext().getProtocol())  //20101213 JGY	    		 
	    		 || "ENVELOP".equals(adapter.getContext().getProtocol())
		    	 || "XECURE".equals(adapter.getContext().getProtocol())	    		 
	    		 || "XECURE2".equals(adapter.getContext().getProtocol())
	    		 || "XECURE3".equals(adapter.getContext().getProtocol())
	    		 || "XC3EPB".equals(adapter.getContext().getProtocol())
	    		 ) {
		    		sb.append("\n(");
			    	sb.append("type=" + adapter.getContext().getLlFieldType());
			    	sb.append(", offset=" + adapter.getContext().getLlFieldOffset());
			    	sb.append(", length=" + adapter.getContext().getLlFieldLength());
			    	sb.append(", ll.field.include=" + adapter.getContext().getLlFieldInclude());
			    	sb.append(", ll.offset.exclude=" + adapter.getContext().getLlOffsetExclude());
			    	sb.append(", ll.include=" + adapter.getContext().getLlInclude());
		    		sb.append(")");
		        }

		    	if ("VARIABLE_LENGTH_HEADER".equals(adapter.getContext().getProtocol())) {  // 20130719 KSH
				    		sb.append("\n(");
					    	sb.append("send.header.length=");
					    	sb.append(adapter.getContext().getSendHeaderLength());
					    	sb.append(", recv.header.length=");
					    	sb.append(adapter.getContext().getRecvHeaderLength());
				    		sb.append(")");
				        }

		    	if ("FIXED_LENGTH_PAYLOAD".equals(adapter.getContext().getProtocol())
		    	 || "INISAFE_PAYLOAD".equals(adapter.getContext().getProtocol())	          // 20100515 JGY
		    	 || "UDP_FIXED_LENGTH_PAYLOAD".equals(adapter.getContext().getProtocol())) {
		    		sb.append("\n(");
			    	sb.append("send.payload.length=");
			    	sb.append(adapter.getContext().getSendPayloadLength());
			    	sb.append(", recv.payload.length=");
			    	sb.append(adapter.getContext().getRecvPayloadLength());
		    		sb.append(")");
		        }

		    	if ("XECURE".equals(adapter.getContext().getProtocol())
		    	 || "XECURE3".equals(adapter.getContext().getProtocol())) {
			    		sb.append("\n(");
				    	sb.append(adapter.getContext().getXecureType());
				    	sb.append(", " + adapter.getContext().getXecureConfigPath());
				    	sb.append(", " + adapter.getContext().getXecureRemoteCert());
			    		sb.append(")");
			    }
		    	if ("XC3EPB".equals(adapter.getContext().getProtocol())) {
		    		sb.append("\n(");
		    		sb.append("XC3EPB");
		    		sb.append(", " + adapter.getContext().getXc3epbPassword());
		    		sb.append(", " + adapter.getContext().getXc3epbConfigPath());
		    		sb.append(")");
		    	}
		    	
		    	if ("INISAFE".equals(adapter.getContext().getProtocol())) {
		    		sb.append("\n(");
		    		sb.append("INISAFE");
			    	sb.append(", " + adapter.getContext().getInisafeConfigPath());
			    	sb.append(", " + adapter.getContext().getInisafeRelatedAdapterGroups());
			    	sb.append(", " + adapter.getContext().getInisafeStartMessage());
			    	sb.append(", " + adapter.getContext().getInisafeStopMessage());
		    		sb.append(")");
		    	}
		    	
		    	if ("INISAFE_2020".equals(adapter.getContext().getProtocol())) {
		    		sb.append("\n(");
		    		sb.append("INISAFE_2020");
			    	sb.append(", " + adapter.getContext().getInisafeConfigPath());
			    	sb.append(", " + adapter.getContext().getInisafeRelatedAdapterGroups());
			    	sb.append(", " + adapter.getContext().getInisafeStartMessage());
			    	sb.append(", " + adapter.getContext().getInisafeStopMessage());
		    		sb.append(")");
		    	}
		    	
		    	if ("INISAFE_NATN".equals(adapter.getContext().getProtocol())) {
		    		sb.append("\n(");
		    		sb.append("INISAFE_NATN");
			    	sb.append(", " + adapter.getContext().getInisafeConfigPath());
			    	sb.append(", " + adapter.getContext().getInisafeRelatedAdapterGroups());
			    	sb.append(", " + adapter.getContext().getInisafeStartMessage());
			    	sb.append(", " + adapter.getContext().getInisafeStopMessage());
		    		sb.append(")");
		    	}
		    	
		    	// JGY 20100515		    	
		    	if ("INISAFE_PAYLOAD".equals(adapter.getContext().getProtocol())) {
		    		sb.append("\n(");
		    		sb.append("INISAFE_PAYLOAD");
			    	sb.append(", " + adapter.getContext().getInisafeConfigPath());
			    	sb.append(", " + adapter.getContext().getInisafeIdPassword());
		    		sb.append(")");
		    	}
		    	
		    	// JGY 20100423
		    	if ("ENVELOP".equals(adapter.getContext().getProtocol())) {
		    		sb.append("\n(");
		    		sb.append("ENVELOP");
			    	sb.append(", " + adapter.getContext().getEnvelopSigncertPath());
			    	sb.append(", " + adapter.getContext().getEnvelopSignkeyPath());
			    	sb.append(", " + adapter.getContext().getEnvelopPassword());
		    		sb.append(")");
		    	}
		    	
		    	// JGY 20101213
		    	if ("TCSEED".equals(adapter.getContext().getProtocol())) {
		    		sb.append("\n(");
		    		sb.append("TCSEED");
			    	sb.append(", " + adapter.getContext().getTcseedKeyStore());;
		    		sb.append(")");
		    	}		    	

		    	if (adapter.getContext().getDescription() != null && !"".equals(adapter.getContext().getDescription().trim())) {
		    		sb.append("\n(" + adapter.getContext().getDescription() + ")");
		    	}
		    	
		    	
	    		row.put("data", sb.toString());
	    		
	    		ArrayList<String> normal = new ArrayList<String>();
	    		StringBuffer sessionsb = null;
			    for (Iterator iii = adapter.getSessionPool().iterator() ; iii.hasNext(); ) {
			    	sessionsb = new StringBuffer();
			    	IoSession session = (IoSession) iii.next();
			    	if (!session.isConnected())
			    		sessionsb.append("●");
			    	else if (session.isClosing())
			    		sessionsb.append("◐");
			    	else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
			    		sessionsb.append("⊙");
			    	else
			    		sessionsb.append("○");
			    	sessionsb.append(" Session :");;
			    	if (session.isClosing())
			    		sessionsb.append(" [CLOSING]");
			    	if (!session.isConnected())
			    		sessionsb.append(" [NOT CONNECTED]");
			    	sessionsb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-") + session.getRemoteAddress());
			    	sessionsb.append(", recv:" + session.getReadMessages());
			    	sessionsb.append("(" + session.getReadBytes() + ")");
			    	sessionsb.append(", send:" + session.getWrittenMessages());
			    	sessionsb.append("(" + session.getWrittenBytes() + ")");
			    	sessionsb.append(", created:" + TimeUtil.formatDate(session.getCreationTime()));
			    	sessionsb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) );
			    	normal.add(sessionsb.toString());
			    }
			    ArrayList<String> delay = new ArrayList<String>();
		    	for (Iterator iii = adapter.getSessionPool().checkedOutIterator() ; iii.hasNext(); ) {
		    		sessionsb = new StringBuffer();
			    	IoSession session = (IoSession) iii.next();
			    	if (!session.isConnected())
			    		sessionsb.append("●");
			    	else if (session.isClosing())
			    		sessionsb.append("◐");
			    	else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
			    		sessionsb.append("⊙");
			    	else
			    		sessionsb.append("○");
			    	sessionsb.append(" Session :");;
			    	if (session.isClosing())
			    		sessionsb.append(" [CLOSING]");
			    	if (!session.isConnected())
			    		sb.append(" [NOT CONNECTED]");
			    	sessionsb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-") + session.getRemoteAddress());
			    	sessionsb.append(", recv:" + session.getReadMessages());
			    	sessionsb.append("(" + session.getReadBytes() + ")");
			    	sessionsb.append(", send:" + session.getWrittenMessages());
			    	sessionsb.append("(" + session.getWrittenBytes() + ")");
			    	sessionsb.append(", created:" + TimeUtil.formatDate(session.getCreationTime()));
			    	sessionsb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) + "\n");
			    	delay.add(sessionsb.toString());
			    }
		    	row.put("normal", normal);
		    	row.put("delay", delay);
		    	list.add(row);
			    prevAdapterGroupName = adapterGroupName;
		    }
	    }		
	    JSONArray array = new JSONArray();
	    array.addAll(list);
        return array.toJSONString();
	}
	
//	private String prop() {
//		return "";
//	}	
	
	protected boolean getAdapterStatus(String adapterGroupName, String adapterName) {
        AdapterManager manager = AdapterManager.getInstance();
        AdapterVO vo = manager.getAdapterVO(adapterGroupName, adapterName);
        if (vo != null) {
        	return vo.isStatus();
        }
        return false;
	}
}
