package com.eactive.eai.rms.onl.adapter.info;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import com.eactive.eai.rms.common.datasource.DataSourceType;
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
import com.eactive.eai.rms.common.util.ContainerUtil;

public class AdapterInfosManager {
	private Context context;

	protected final Logger logger = Logger.getLogger(getClass());

    
	//모니터링을 위한 정보를 저장할 VO
	public static HashMap<String,AdapterInfosVO> adaptersMap = null;
	
	public AdapterInfosManager() {
		this.init();
	}

	/** singleton 구현을 위한 자신의 instance */
	private static AdapterInfosManager instance ;
	
	public void init() {
	 //RMS가 기동할 때 인스턴스별로 돌면서 개별 DB의 어뎁터를 불러옴
		try {
			if (ContainerUtil.get() == ContainerUtil.TOMCAT) {
				Context initContext = new InitialContext();
				context = (Context) initContext.lookup("java:/comp/env");
			}
			else {
				context = new InitialContext();
			}
		} catch (Exception e) {
			//취약점소스 수정 2020.08.24
			logger.error(" error", e); 
		}
		loadAdapterInfos();
	}
	
	@Autowired
	public static AdapterInfosManager getInstance() {
		synchronized (AdapterInfosManager.class) {
			if (instance == null) {
	            instance = new AdapterInfosManager();
			}
			return instance;
        }
	}
	
	public void loadAdapterInfos() {
		
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			adaptersMap = new HashMap<String,AdapterInfosVO>();
			//int i = 0;
			for(DataSourceType d : DataSourceTypeManager.getOnlineDataSourceTypes() ) {
				logger.info(" Adapter 정보 구성을 위한  db 접속 ==> " + d.toString());
				// Source Connection
				conn = getConnection(d.getJndiName());
				 if(conn != null) { //취약점소스 수정 2020.08.25
					 stmt = conn.prepareStatement(makeSqlStatus(d.getSchema()));
				 }
				
				  if(stmt != null) { //취약점소스 수정 2020.08.26
					  rs = stmt.executeQuery();
				  }
				while ( rs.next() ) {
					
					if(rs != null){  //취약점소스 수정 2020.08.26
						//AdapterInfosVO 처리
						AdapterInfosVO avo = new AdapterInfosVO();
						//HASHMAP에 있는 어뎁터인지를 먼저 확인함
						avo.setAdptrBzwkGroupName(rs.getString(1));
						if ( adaptersMap.containsKey(avo.getAdptrBzwkGroupName()) ) {
							avo = adaptersMap.get(avo.getAdptrBzwkGroupName());
							avo.ALEAISevrInstncName.add(rs.getString(3));
						} else {
							avo.setAdptrBzwkGroupDesc(rs.getString(2));
							avo.ALEAISevrInstncName.add(rs.getString(3));
							avo.setSocketType(rs.getString(4));
							avo.setOsidInstiBzwkRsempName(rs.getString(5));
							avo.setOsidInstiTelno(rs.getString(6));
							avo.setBoundType(rs.getString(7));
							//tobe 추가
							avo.setPermanent(rs.getString(8));
							avo.setHostName(rs.getString(9));
							avo.setPortNumber(rs.getString(10));
						}
						adaptersMap.put(avo.getAdptrBzwkGroupName(), avo);
					}
					
				}
				closeConnection(conn, stmt, rs);
			}
		} catch (Exception e) {
			//e.printStackTrace(); //취약점소스 수정 2020.08.24
			logger.error(" DB Source CONNECTION FAIL");
		} finally {
			closeConnection(conn, stmt, rs);
		}
	}
	
	public Connection getConnection(String datasource) throws Exception {
		try {
			DataSource ds = null;
			if(context != null){ //취약점소스 수정 2020.08.24
				ds = (DataSource) context.lookup(datasource);
			}
			if(ds != null){ //취약점소스 수정 2020.08.24
				return ds.getConnection();
			}else{
				return null;
			}
			
		} catch (Exception e) {
			throw e;
		}
	}

	protected void closeConnection(Connection con, Statement stmt, ResultSet rs) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				;
			}
		}
		
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				;
			}
		}
		if (con != null) {
			try {
				if (!con.isClosed()) {
					con.close();
				}
			} catch (SQLException e) {
				;
			}
		}
	}
	
	
	public static HashMap<String, AdapterInfosVO> getAdaptersMap() {
		return adaptersMap;
	}

	public static void setAdaptersMap(HashMap<String, AdapterInfosVO> adaptersMap) {
		AdapterInfosManager.adaptersMap = adaptersMap;
	}
	
	public void updateAdapterInfo(AdapterInfosVO aptinfo) {
		adaptersMap.put(aptinfo.getAdptrBzwkGroupName(), aptinfo);
	}
	
	public void removeAdapterInfo(String adptrName) {
		if ( adaptersMap.containsKey(adptrName) )
			adaptersMap.remove(adptrName);
	}
	
	public AdapterInfosVO getAdapterVOInfo(String adptrName) {
		if ( adaptersMap.containsKey(adptrName) )
			return adaptersMap.get(adptrName);
		return new AdapterInfosVO();
	}

	public String toString() {
		
//		System.out.println("---------------- Display START -------------------");
		Collection<AdapterInfosVO> coll = AdapterInfosManager.adaptersMap.values();
		Iterator<AdapterInfosVO> iter = coll.iterator();
		
		while (iter.hasNext()) {
			AdapterInfosVO tempVO = iter.next();
//			System.out.println(tempVO.toString());
		}
		
		return new String("---------------- Display END -------------------" );
	}
	
	public String makeSqlStatus(String schemaId) {
		String SqlString = new String();
		
		SqlString = 
						"SELECT "
						+ "\n A.ADPTRBZWKGROUPNAME, " 
						+ "\n A.ADPTRBZWKGROUPDESC, " 
						+ "\n B.EAISEVRINSTNCNAME, " 
						+ "\n TAB1.SOCKETTYPE AS \"SOCKETTYPE\", "
						+ "\n A.OSIDINSTITELNO, "
						+ "\n A.OSIDINSTIBZWKRSEMPNAME , " 
						+ "\n TAB2.BOUNDTYPE AS \"BOUNDTYPE\" , " 
						+ "\n TAB3.PERMANENT AS \"PERMANENT\", " 
						+ "\n TAB4.HOSTNAME AS \"HOSTNAME\" ,"
						+ "\n TAB5.PORTNUMBER AS \"PORTNUMBER\" "
						+ "\n FROM  " +  schemaId + ".TSEAIAD01 A, " 
						+ "\n 	" +  schemaId + ".TSEAIAD02 B, " 
						+ "\n 	( SELECT C.PRPTYGROUPNAME, " 
						+ "\n 	C.PRPTY2VAL	AS SOCKETTYPE "
						+ "\n 	FROM " +  schemaId + ".TSEAIAD15 C "
						+ "\n 	WHERE C.PRPTYNAME = 'socket.type' "
						+ "\n 	)   TAB1, " 
						+ "\n 	( SELECT C.PRPTYGROUPNAME , "
						+ "\n 	C.PRPTY2VAL	AS BOUNDTYPE "
						+ "\n 	FROM " +  schemaId + ".TSEAIAD15 C "
						+ "\n 	WHERE C.PRPTYNAME = 'bound.usage' "
						+ "\n 	)   TAB2, " 
						+ "\n 	( SELECT C.PRPTYGROUPNAME , "
						+ "\n 	C.PRPTY2VAL	AS PERMANENT "
						+ "\n 	FROM " +  schemaId + ".TSEAIAD15 C  "
						+ "\n 	WHERE C.PRPTYNAME = 'permanent' "
						+ "\n 	)   TAB3, " 
						+ "\n 	( SELECT C.PRPTYGROUPNAME , "
						+ "\n 	C.PRPTY2VAL	AS HOSTNAME "
						+ "\n 	FROM " +  schemaId + ".TSEAIAD15 C "
						+ "\n 	WHERE C.PRPTYNAME = 'host.name' "
						+ "\n 	)   TAB4 , "
						+ "\n 	( SELECT C.PRPTYGROUPNAME , "
						+ "\n 	C.PRPTY2VAL	AS PORTNUMBER "
						+ "\n 	FROM " +  schemaId + ".TSEAIAD15 C  "
						+ "\n 	WHERE C.PRPTYNAME = 'port.number' "
						+ "\n 	)   TAB5 "
						+ "\n WHERE A.ADPTRCD = 'NET' "
						+ "\n AND A.ADPTRBZWKGROUPNAME = B.ADPTRBZWKGROUPNAME "
						+ "\n AND B.PRPTYGROUPNAME = TAB1.PRPTYGROUPNAME "
						+ "\n AND B.PRPTYGROUPNAME = TAB2.PRPTYGROUPNAME "
						+ "\n AND B.PRPTYGROUPNAME = TAB3.PRPTYGROUPNAME "
						+ "\n AND B.PRPTYGROUPNAME = TAB4.PRPTYGROUPNAME "
						+ "\n AND B.PRPTYGROUPNAME = TAB5.PRPTYGROUPNAME "
						+ "\n ORDER BY 1, 3, 4  "
						+ "\n WITH UR";
//		System.out.println(SqlString);
		return SqlString;
	}
	
	
	public List<Map<String, String>> getEaiServerIpList(String name) {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet 			rs = null;
		List<Map<String, String>> list = new ArrayList<Map<String, String>>();
		try {
			//int i = 0;
			
			DataSourceType d = DataSourceTypeManager.getDataSourceType(name); 
			
			logger.debug(" Adapter 정보 구성을 위한  db 접속 ==> " + name +"=" + d);
			
			if(d == null) {
				return list;
			}
			
			// Source Connection
			conn = getConnection(d.getJndiName());
			 if(conn != null) {//취약점소스 수정 2020.08.25
				 stmt = conn.prepareStatement(makeSqlInst(d.getSchema()));
			 }
			 if(stmt != null) { //취약점소스 수정 2020.08.27
				 rs = stmt.executeQuery();
			 }
			
			 if(rs != null){  //취약점소스 수정 2020.08.26
				 while ( rs.next() ) {
					HashMap<String, String> map = new HashMap<String, String>(); 
					map.put("EAISVRINSTNM", rs.getString("EAISVRINSTNM"));
					map.put("EAISVRIP", rs.getString("EAISVRIP"));
					map.put("EAISVRLSNPORT", rs.getString("EAISVRLSNPORT"));
					map.put("HOSTNAME", rs.getString("HOSTNAME"));
					map.put("FAILOVERSVRNM", rs.getString("FAILOVERSVRNM"));
					list.add(map);
				}
			}			
		} catch (Exception e) {
			//e.printStackTrace(); //취약점소스 수정 2020.08.24
			logger.error(" DB Source CONNECTION FAIL");
		} finally {
			closeConnection(conn, stmt, rs);
		}
		return list;
	}
	
	public String makeSqlInst(String schemaId) {
		String SqlString = new String();
		
		SqlString = 
				"\n SELECT EAISEVRINSTNCNAME AS \"EAISVRINSTNM\",  EAISEVRIP  AS \"EAISVRIP\"   , "
						+"\n 		       SEVRLSNPORTNAME   AS \"EAISVRLSNPORT\", FLOVRSEVRNAME AS \"FAILOVERSVRNM\", "
						+"\n 		       HOSTNAME  AS \"HOSTNAME\"         "
						+"\n 		FROM   " +  schemaId + ".TSEAISY02 "
						+"\n 		WHERE  EAISEVRINSTNCNAME != 'ALL' "
						+"\n 		AND    EAISEVRIP != '*' "
						+"\n 		ORDER   BY EAISEVRIP, SEVRLSNPORTNAME ASC";
		
		return SqlString;
	}
}

