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

import com.eactive.eai.adapter.*;
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.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

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

	protected void doService(HttpRequest request, HttpResponse response) throws Exception {
		String option = request.getContext();
    	if (option.lastIndexOf('/') == -1) {
    		option = "";
    	} else {
    		option = option.substring(option.indexOf('/')+1);
    	}

    	String result = show("full".equals(option));
		
		response.setContentType("text/xml");
		response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
		response.appendBody("<?xml version=\"1.0\" encoding=\"euc-kr\"?>\n");
		response.appendBody(result); //.getBytes("UTF-8"));
	}

	private String show(boolean checkConnect) throws Exception {
        Document document = DocumentHelper.createDocument();
        Element root = document.addElement("adapters");        
        
        /**
         * [1] Socket Adapter
         */
		ConcurrentHashMap adapterGroups = (ConcurrentHashMap) SocketAdapterManager.getInstance().getSocketAdapterGroups();
	    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();		
		        Element adapterNode = root.addElement("adapter");
		        adapterNode.addElement("name").addText(adapter.getContext().getAdapterName());
		        adapterNode.addElement("type").addText("socket");
		        adapterNode.addElement("group").addText(adapterGroupName);
		        adapterNode.addElement("desc").addText(adapter.getContext().getDescription());
		        
		        /**
		         * status
		         */
		        String cause = "";
		        if (adapter.getContext().isServer()) {
		        	if (adapter.getState() == ISocketAdapter.State.STARTED) {
		        		if (adapter.getContext().isPermanent()) {
		        			if (adapter.getSessionPool().peekSize() > 0) {
		        				adapterNode.addElement("status").addText("O");
		        			} else {
		        				adapterNode.addElement("status").addText("X");
		        				cause = "SERVER/PERMANENT - no established session";
		        			}
		        		} else {
		        			adapterNode.addElement("status").addText("O");
		        		}
		        	} else {
		        		adapterNode.addElement("status").addText("X");
        				cause = "SERVER - adapter not started, adapter status = " + adapter.getState().name();
		        	}
		        } else {
		        	if (adapter.getState() == ISocketAdapter.State.STARTED) {
		        		if (adapter.getContext().isPermanent()) {
		        			if (adapter.getSessionPool().peekSize() > 0) {
		        				adapterNode.addElement("status").addText("O");
		        			} else {
		        				adapterNode.addElement("status").addText("X");
		        				cause = "CLIENT/PERMANENT - no established session";
		        			}
		        		} else {
		        			try {
		        				checkRemote(adapter.getContext().getHostName(), adapter.getContext().getPortNumber(), checkConnect);
		        				adapterNode.addElement("status").addText("O");
		        			} catch(Exception ex) {
		        				adapterNode.addElement("status").addText("X");
		        				cause = "CLIENT/NON-PERM - cannot connect remote server - " + ex.getMessage();
		        			}
		        		}
		        	} else {
		        		if ("INISAFE".equals(adapter.getContext().getProtocol())) {
			        		adapterNode.addElement("status").addText("O");
		        		}
		        		else if ("INISAFE_2020".equals(adapter.getContext().getProtocol())) {
			        		adapterNode.addElement("status").addText("O");
		        		}
		        		else if ("INISAFE_NATN".equals(adapter.getContext().getProtocol())) {
			        		adapterNode.addElement("status").addText("O");
		        		}
		        		else {
			        		adapterNode.addElement("status").addText("X");
	        				cause = "CLIENT - adapter not started, adapter status = " + adapter.getState().name();
		        		}
		        	}
		        }
		        
		        adapterNode.addElement("cause").addText(cause);
		    }
	    }
	    
	    /**
	     * [2] Http Adapter
	     */
		List groups = AdapterManager.getInstance().getAllAdapterGroupNames();
	    for (Iterator iter = groups.iterator(); iter.hasNext();) {
	    	String groupName = (String) iter.next();   	
	    	AdapterGroupVO groupVO = AdapterManager.getInstance().getAdapterGroupVO(groupName);
	    	
	    	if (!"HTT".equals(groupVO.getType()) 
		    		&& !"HQS".equals(groupVO.getType())
		    		&& !"HXC".equals(groupVO.getType())) {
		    		continue;
		    	}

	    	for (Iterator iter2 = groupVO.getAdapters() ; iter2.hasNext() ;) {
		    	AdapterVO adapterVO = (AdapterVO) iter2.next();		
		    	//PropGroupVO propGroupVO = PropManager.getInstance().getPropGroupVO(adapterVO.getPropGroupName());
		    	AdapterPropGroupVO propGroupVO = AdapterPropManager.getInstance().getAdapterPropGroupVO(adapterVO.getPropGroupName());
		        Element adapterNode = root.addElement("adapter");
		        adapterNode.addElement("name").addText(adapterVO.getName());
		        adapterNode.addElement("type").addText("http");
		        adapterNode.addElement("group").addText(groupName);
		        adapterNode.addElement("desc").addText(adapterVO.getDescription());
		        
		        //adapterNode.addElement("status").addText(adapterVO.getListenerClass());
		        //adapterNode.addElement("cause").addText(adapterVO.getPropGroupName());
		        
		        /**
		         * status
		         */
		        String cause = "";
		        if ("I".equals(groupVO.getGubun())) {
		        	if (adapterVO.isStatus()) {
	        			adapterNode.addElement("status").addText("O");
		        	} else {
		        		adapterNode.addElement("status").addText("X");
		        	}
		        } else {
		        	if (adapterVO.isStatus()) {
        				String urlString = propGroupVO.getProperty("URL");
	        			try {
	        				URL url = new URL(urlString);
	        				checkRemote(url.getHost(), url.getPort(), checkConnect);
	        				adapterNode.addElement("status").addText("O");
	        			} catch(SocketTimeoutException ex) {
	        				adapterNode.addElement("status").addText("X");
	        				cause = "CLIENT - cannot connect remote server - " + urlString;
	        			} catch(Exception ex) {
	        				adapterNode.addElement("status").addText("X");
	        				cause = ex.getMessage();
	        			}
		        	} else {
		        		adapterNode.addElement("status").addText("X");
		        	}
		        }
		        
		        adapterNode.addElement("cause").addText(cause);
		    }
	    }
	    
	    return root.asXML();
	}
	
	private boolean checkRemote(String host, int port, boolean checkConnect) throws Exception {
		if (!checkConnect) {
			return true;
		}
		
		Socket socket = null;
		try {
			socket = new Socket();
			socket.connect(new InetSocketAddress(host, port), 2000);
			return true;
		} finally {
			if (socket != null)
				try { socket.close(); } catch(Exception e) {}
		}
	}
}
