 package com.eactive.eai.agent; 

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Properties;
import java.net.ProtocolException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
import javax.naming.Context;
import javax.naming.InitialContext;

import com.eactive.eai.agent.command.Command;
import com.eactive.eai.agent.command.CommandException;
import com.eactive.eai.common.dao.DAOFactory;
import com.eactive.eai.common.server.EAIServerDAO;
import com.eactive.eai.common.server.EAIServerManager;
import com.eactive.eai.common.server.EAIServerVO;
import com.eactive.eai.common.util.ApplicationContextProvider;
import com.eactive.eai.common.util.Logger;

/** 
* 1. 기능 : 등록된 EAI Server 에 Command를 broadcast
* 2. 처리 개요 : 등록된 EAI Server 에 Command를 broadcast
* 3. 주의사항 
*
* @author  
* @version  v 1.0.0
* @see  관련 기능을 참조
* @since  
*  
*/
public class AgentUtil 
{
    static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
    final static String SERVLET_URL = "/ESBWeb/WebAgent";
    
    private static HashMap returnValue;
    
    /** 
    * 1. 기능 :  AgentUtil 기본 생성자
    * 2. 처리 개요 : 
    * 3. 주의사항 
    *
    * @param 
    * @return 
    * @exception
    **/
	private AgentUtil(){
        returnValue = new HashMap();
    }
 
    /** 
    * 1. 기능 :  등록된 EAI Server 의 URL을 생성하여 반환
    * 2. 처리 개요 : EAIServerDAO를 통해 데이터베이스에 등록된 EAI Server의 URL을 생성하여 반환
    * 3. 주의사항 
    *
    * @param 
    * @return   HashMap 등록된 EAI Server 의 URL.
    * @exception    Exception
    **/
     private static HashMap getAllSvrUrl()throws Exception{

        Map<String, EAIServerVO> servers = new HashMap<>();
        HashMap urlLists = new HashMap();
        
        servers =  EAIServerManager.getInstance().getAllServer(false);
           
        Iterator it = servers.keySet().iterator(); 
        String svrName = "";
        while( it.hasNext()){
            svrName = (String)it.next();
            try{
            	if(! ("ALL".equalsIgnoreCase(svrName))){
	                StringBuffer    urlBuf  = new StringBuffer();
	                EAIServerVO vo = (EAIServerVO)servers.get(svrName);
                    if(vo != null){
                        urlBuf.append(vo.toURL(EAIServerVO.HTTP_PROTOCOL));
                        urlBuf.append(SERVLET_URL);
                        logger.debug("AgentUtil] getAllSvrUrl - URL : "+urlBuf.toString());
         
                        urlLists.put(svrName, urlBuf.toString());
                    }
                    else {
                        logger.error("AgentUtil] getAllSvrUrl - BroadCast할 서버 정보를 가져올 수 없습니다. ");
                    }
	         }

            }catch (Exception e){
               logger.error("AgentUtil] getAllSvrUrl Error. - "+e.getMessage());
            }
        }
        return urlLists;
      
     }

     /**
      * temp code for test
      */
//    private static HashMap getServerUrl()  {
// 
//        HashMap urls = new HashMap();
//        
//        urls.put("cgServer", "http://172.17.51.127:8001/ESBWeb/WebAgent");
//   //     urls.put("cgServer2", "http://172.17.51.127:7001/ESBWeb/WebAgent");    
//        return urls;
//    
//  }
  
    /** 
    * 1. 기능 :  등록된 EAI Server에 Command를 broadcast
    * 2. 처리 개요 : 등록된 EAI Server의 URLConnection을 생성하여 Command broadcast하고
    *               전송된 결과값의 HashMap을 생성하여 반환 
    * 3. 주의사항 
    *
    * @param    svrName     broadcast할 EAI Server명
    * @param    url         broadcast할 EAI Server의 url
    * @param    command     broadcast할 Command
    * @return   HashMap     broadcast후 전송된 결과값. 
    *                       전송된 데이터가 success가 아니면 Exception이 전송된 것임.
    * @exception    Exception
    **/
    public static HashMap broadcast(String svrName, String url, Command command)throws Exception{
        URLConnection urlCon;
        String response = "";
        
        if(returnValue == null){
            returnValue = new HashMap();   
        }

        if(url !=null){
            urlCon = getURLConnection(url);
            try{
                response = sendCommand(urlCon, command);
                returnValue.put(svrName, response);
            }catch (Exception e){
                logger.error("AgentUtil] broadcast Excpetion", e);
                returnValue.put(svrName, e.getMessage());
            }
            
        }else{
            logger.error("AgentUtil] broadcast Error. - url is null");    
        } 
        return returnValue;
    }
    
    /** 
    * 1. 기능 :  등록된 EAI Server에 Command를 broadcast
    * 2. 처리 개요 : 등록된 EAI Server의 URLConnection을 생성하여 Command broadcast하고
    *               전송된 결과값의 HashMap을 생성하여 반환 
    * 3. 주의사항 
    *
    * @param    command     broadcast할 Command
    * @return   HashMap     broadcast후 전송된 결과값. 
    *                       전송된 데이터가 success가 아니면 Exception이 전송된 것임.
    * @exception    Exception
    **/
    public static HashMap broadcast(Command command)throws Exception{
        URLConnection urlCon;
        HashMap servers = getAllSvrUrl();
 //       HashMap servers = getServerUrl();
        
        if(returnValue == null){
            returnValue = new HashMap();   
        }
       
        if(servers != null){
            Iterator it = servers.keySet().iterator(); 
            String svrName = "";
            String url = "";
            String response = "";
            
            while( it.hasNext()){
                svrName = (String)it.next();
                url = (String) servers.get(svrName);
                
                urlCon = getURLConnection(url);
                try{
                    response = sendCommand(urlCon, command);
                    returnValue.put(svrName, response);
                }catch (Exception e){
                    logger.error("AgentUtil] broadcast Excpetion - "+url+ e.getMessage());
                    returnValue.put(svrName, e.getMessage());
                }
            }
        }else{
            logger.error("AgentUtil] broadcast Error. - url is null"); 
               
        }
        return returnValue;
     }
     
	 

    /** 
    * 1. 기능 :  해당 URLConnection으로 command 전송 처리 결과를 반환
    * 2. 처리 개요 : 해당 URLConnection으로 command 전송하고 처리 결과를 반환
    * 3. 주의사항 
    *
    * @param    urlCon  연결할 URLConnection
    * @param    command 전송할 Command
    * @return   String 처리된 결과 
    * @exception    Exception
    **/
     public static String sendCommand(URLConnection urlCon, Command command)throws Exception{
        ObjectOutputStream oos          = null;
        ObjectInputStream  ois          = null;
        String             response     = "";
        
        try {
            oos = new ObjectOutputStream(urlCon.getOutputStream());
            oos.writeObject(command);
            oos.flush();
            logger.debug("AgentUtil] SendCommand - "+urlCon.getURL().toString());
            
            ois = new ObjectInputStream(urlCon.getInputStream());
            response = (String)ois.readObject();
                
        } catch (ConnectException e) {
            logger.error("AgentUtil] sendCommand ConnectException. - "+urlCon.getURL()+ " can't Connect"+e.getMessage());
            throw e;
        } catch (IOException e2) {
            logger.error("AgentUtil] sendCommand IOException. - "+urlCon.getURL()+ " can't IO" +e2.getMessage());
            throw e2;
        } catch (Exception e) {
            logger.error("AgentUtil] sendCommand Exception. - "+urlCon.getURL()+e.getMessage());
            throw e;
        } finally {            
                if (oos != null) try { oos.close(); } catch (Exception e) { oos = null; }
                if (ois != null) try { ois.close(); } catch (Exception e) { ois = null; }
        }
        return response;
    }  
      
     /** 
    * 1. 기능 :  지정된  url의 URLConnection 생성
    * 2. 처리 개요 : 지정된  url의 URLConnection 생성
    * 3. 주의사항 
    *
    * @param    url     URLConnection을 생성을 위한 url
    * @return   URLConnection 생성된 URLConnection
    * @exception
    **/    
     public static URLConnection getURLConnection(String url) {
		URL u = null;
		try {
			u = new URL(url);
		} catch (MalformedURLException e) {
			logger.error("AgentUtil] getURLConnection ", e);
		}

		HttpURLConnection conn = null;

		try {
			conn = (HttpURLConnection) u.openConnection();
		} catch (Exception e) {
			logger.error("openConnection error", e);
        }
        
        if(conn != null){
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setUseCaches(false);
        }
        else{
            logger.error("AgentUtil] getURLConnection Error. - " + url +" 의 HttpURLConnection 을 생성할 수 없습니다.");
        }

		try {
            if(conn != null){
                conn.setRequestMethod("POST");
            }
		} catch (ProtocolException pe) {
            logger.error("AgentUtil] getURLConnection ", pe);
		}
		if(conn != null){
            conn.setRequestProperty("Content-type", "application/octet-stream");
        }
		return conn;
	}
    
}