/*

Copyright (C) 2008 NTT DATA INTELLILINK CORPORATION

This program is free software; you can redistribute it and/or
Modify it under the terms of the GNU General Public License 
as published by the Free Software Foundation, version 2.

This program is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied 
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
PURPOSE.  See the GNU General Public License for more details.

 */

package jp.co.intellilink.hinemos.test.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;

import javax.ejb.FinderException;
import javax.naming.NamingException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jnp.interfaces.NamingContext;

import com.clustercontrol.bean.Property;
import com.clustercontrol.hinemosagent.ejb.session.MonitorAgentController;
import com.clustercontrol.hinemosagent.ejb.session.MonitorAgentControllerHome;
import com.clustercontrol.http.ejb.session.MonitorHttpController;
import com.clustercontrol.http.ejb.session.MonitorHttpControllerHome;
import com.clustercontrol.jobmanagement.ejb.session.JobController;
import com.clustercontrol.jobmanagement.ejb.session.JobControllerHome;
import com.clustercontrol.logtransfer.ejb.session.LogTransferController;
import com.clustercontrol.logtransfer.ejb.session.LogTransferControllerHome;
import com.clustercontrol.maintenance.ejb.session.MaintenanceController;
import com.clustercontrol.maintenance.ejb.session.MaintenanceControllerHome;
import com.clustercontrol.monitor.bean.ReportEventInfo;
import com.clustercontrol.monitor.ejb.session.MonitorController;
import com.clustercontrol.monitor.ejb.session.MonitorControllerHome;
import com.clustercontrol.monitor.factory.EventFilterProperty;
import com.clustercontrol.notify.bean.NotifyInfo;
import com.clustercontrol.notify.ejb.entity.NotifyActionInhibitionInfo;
import com.clustercontrol.notify.ejb.entity.NotifyActionInhibitionInfoHome;
import com.clustercontrol.notify.ejb.entity.NotifyActionInhibitionInfoPK;
import com.clustercontrol.notify.ejb.session.NotifyController;
import com.clustercontrol.notify.ejb.session.NotifyControllerHome;
import com.clustercontrol.notify.monitor.ejb.entity.StatusInfoData;
import com.clustercontrol.performance.ejb.session.CollectorController;
import com.clustercontrol.performance.ejb.session.CollectorControllerHome;
import com.clustercontrol.performance.monitor.ejb.session.MonitorPerfController;
import com.clustercontrol.performance.monitor.ejb.session.MonitorPerfControllerHome;
import com.clustercontrol.ping.ejb.session.MonitorPingController;
import com.clustercontrol.ping.ejb.session.MonitorPingControllerHome;
import com.clustercontrol.port.ejb.session.MonitorPortController;
import com.clustercontrol.port.ejb.session.MonitorPortControllerHome;
import com.clustercontrol.process.ejb.session.MonitorProcessController;
import com.clustercontrol.process.ejb.session.MonitorProcessControllerHome;
import com.clustercontrol.repository.ejb.session.RepositoryController;
import com.clustercontrol.repository.ejb.session.RepositoryControllerHome;
import com.clustercontrol.snmp.ejb.session.MonitorSnmpController;
import com.clustercontrol.snmp.ejb.session.MonitorSnmpControllerHome;
import com.clustercontrol.snmptrap.ejb.session.MonitorSnmpTrapController;
import com.clustercontrol.snmptrap.ejb.session.MonitorSnmpTrapControllerHome;
import com.clustercontrol.sql.ejb.session.MonitorSqlController;
import com.clustercontrol.sql.ejb.session.MonitorSqlControllerHome;
import com.clustercontrol.syslogng.ejb.session.SyslogNGController;
import com.clustercontrol.syslogng.ejb.session.SyslogNGControllerHome;
import com.clustercontrol.util.PropertyUtil;

/**
 * EJBとのコネクションを管理するクラス<br>
 * 
 * @version 1.0.0
 * @since 1.0.0
 */
public class EjbConnectionManager {

	// ログ出力
	private static Log log = LogFactory.getLog(EjbConnectionManager.class);

	/** シングルトン用インスタンス。 */
	private static EjbConnectionManager m_instance = null;
	/** コンテキスト。 */
	private NamingContext m_ctx = null;
	/** 通知情報マップ */
	private HashMap<String, NotifyInfo> notifyList = null;
	/** イベント情報マップ */
	private HashMap<String, ArrayList<ReportEventInfo>> eventList = null;

	private EjbConnectionManager() {
	}

	/**
	 * 本クラスのインスタンスを返します。<br>
	 * 
	 * @return 唯一のインスタンス
	 */
	public static EjbConnectionManager getConnectionManager() {
		if (m_instance == null) {
			m_instance = new EjbConnectionManager();
		}
		return m_instance;
	}

	/**
	 * 通知機能 SessionBean のインスタンスを返します。<br>
	 * 
	 * @return 通知機能 SessionBean
	 */
	public synchronized NotifyController getNotifyController() {
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		NotifyControllerHome home;
		try {
			home = (NotifyControllerHome) m_ctx
			.lookup(NotifyControllerHome.JNDI_NAME);
			return home.create();
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * エージェント監視機能 SessionBean のインスタンスを返します。<br>
	 * 
	 * @return エージェント監視機能 SessionBean
	 */
	public synchronized MonitorAgentController getMonitorAgentController() {
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		MonitorAgentControllerHome home;
		try {
			home = (MonitorAgentControllerHome) m_ctx
			.lookup(MonitorAgentControllerHome.JNDI_NAME);
			return home.create();
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * HTTP監視機能 SessionBean のインスタンスを返します。<br>
	 * 
	 * @return HTTP監視機能 SessionBean
	 */
	public synchronized MonitorHttpController getMonitorHttpController() {
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		MonitorHttpControllerHome home;
		try {
			home = (MonitorHttpControllerHome) m_ctx
			.lookup(MonitorHttpControllerHome.JNDI_NAME);
			return home.create();
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * Ping監視機能 SessionBean のインスタンスを返します。<br>
	 * 
	 * @return Ping監視機能 SessionBean
	 */
	public synchronized MonitorPingController getMonitorPingController() {
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		MonitorPingControllerHome home;
		try {
			home = (MonitorPingControllerHome) m_ctx
			.lookup(MonitorPingControllerHome.JNDI_NAME);
			return home.create();
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * サービス・ポート監視機能 SessionBean のインスタンスを返します。<br>
	 * 
	 * @return サービス・ポート監視機能 SessionBean
	 */
	public synchronized MonitorPortController getMonitorPortController() {
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		MonitorPortControllerHome home;
		try {
			home = (MonitorPortControllerHome) m_ctx
			.lookup(MonitorPortControllerHome.JNDI_NAME);
			return home.create();
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * SNMP監視機能 SessionBean のインスタンスを返します。<br>
	 * 
	 * @return SNMP監視機能 SessionBean
	 */   
	public synchronized MonitorSnmpController getMonitorSnmpController() {
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		MonitorSnmpControllerHome home;
		try {
			home = (MonitorSnmpControllerHome) m_ctx
			.lookup(MonitorSnmpControllerHome.JNDI_NAME);
			return home.create();
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * プロセス監視機能 SessionBean のインスタンスを返します。<br>
	 * 
	 * @return プロセス監視機能 SessionBean
	 */
	public synchronized MonitorProcessController getMonitorProcessController() {
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		MonitorProcessControllerHome home;
		try {
			home = (MonitorProcessControllerHome) m_ctx
			.lookup(MonitorProcessControllerHome.JNDI_NAME);
			return home.create();
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * リソース監視機能 SessionBean のインスタンスを返します。<br>
	 * 
	 * @return リソース監視機能 SessionBean
	 */
	public synchronized MonitorPerfController getMonitorPerfController() {  	
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		MonitorPerfControllerHome home;
		try {
			home = (MonitorPerfControllerHome) m_ctx
			.lookup(MonitorPerfControllerHome.JNDI_NAME);
			return home.create();
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * SQL監視機能 SessionBean のインスタンスを返します。<br>
	 * 
	 * @return SQL監視機能 SessionBean
	 */
	public synchronized MonitorSqlController getMonitorSqlController() {
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		MonitorSqlControllerHome home;
		try {
			home = (MonitorSqlControllerHome) m_ctx
			.lookup(MonitorSqlControllerHome.JNDI_NAME);
			return home.create();
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * SNMPTRAP監視機能 SessionBean のインスタンスを返します。<br>
	 * 
	 * @return SNMPTRAP監視機能 SessionBean
	 */
	public synchronized MonitorSnmpTrapController getMonitorSnmpTrapController() {
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		MonitorSnmpTrapControllerHome home;
		try {
			home = (MonitorSnmpTrapControllerHome) m_ctx
			.lookup(MonitorSnmpTrapControllerHome.JNDI_NAME);
			return home.create();
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * syslog-ng監視機能 SessionBean のインスタンスを返します。<BR>
	 * 
	 * @return syslog-ng監視機能 SessionBean
	 */
	public synchronized SyslogNGController getMonitorSyslogNGController() {
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		SyslogNGControllerHome home;
		try {
			home = (SyslogNGControllerHome) m_ctx
			.lookup(SyslogNGControllerHome.JNDI_NAME);
			return home.create();
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * メンテナンス機能 SessionBean のインスタンスを返します。<BR>
	 * 
	 * @return メンテナンス機能 SessionBean
	 */
	public synchronized MaintenanceController getMaintenanceController() {
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		MaintenanceControllerHome home;
		try {
			home = (MaintenanceControllerHome) m_ctx
			.lookup(MaintenanceControllerHome.JNDI_NAME);
			return home.create();
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * ログ転送機能 SessionBean のインスタンスを返します。<BR>
	 * 
	 * @return ログ転送機能 SessionBean
	 */
	public synchronized LogTransferController getLogTransferController() {
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		LogTransferControllerHome home;
		try {
			home = (LogTransferControllerHome) m_ctx
			.lookup(LogTransferControllerHome.JNDI_NAME);
			return home.create();
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * 性能管理機能 SessionBean のインスタンスを返します。<BR>
	 * 
	 * @return 性能管理機能 SessionBean
	 */
	public synchronized CollectorController getCollectorController() {
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		CollectorControllerHome home;
		try {
			home = (CollectorControllerHome) m_ctx
			.lookup(CollectorControllerHome.JNDI_NAME);
			return home.create();
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * リポジトリ機能 SessionBean のインスタンスを返します。<BR>
	 * 
	 * @return リポジトリ機能 SessionBean
	 */
	public synchronized RepositoryController getRepositoryController() {
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		RepositoryControllerHome home;
		try {
			home = (RepositoryControllerHome) m_ctx
			.lookup(RepositoryControllerHome.JNDI_NAME);
			return home.create();
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * 監視管理機能 SessionBean のインスタンスを返します。<BR>
	 * 
	 * @return 監視管理機能 SessionBean
	 */
	public synchronized MonitorController getMonitorController() {
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		MonitorControllerHome home;
		try {
			home = (MonitorControllerHome) m_ctx
			.lookup(MonitorControllerHome.JNDI_NAME);
			return home.create();
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * ジョブ管理機能 SessionBean のインスタンスを返します。<BR>
	 * 
	 * @return ジョブ管理機能 SessionBean
	 */
	public synchronized JobController getJobController() {
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		JobControllerHome home;
		try {
			home = (JobControllerHome)m_ctx.lookup(JobControllerHome.JNDI_NAME);
			return home.create();
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * 通知抑制情報 EnbtityBean のインスタンスを返します。<br>
	 * 
	 * @param notifyGroupId 通知グループID
	 * @param notifyId 通知ID
	 * @param facilityId ファシリティID
	 * @return 通知抑制情報 EnbtityBean
	 */
	public synchronized NotifyActionInhibitionInfo getNotifyActionInhibition(
			String notifyGroupId, String notifyId, String facilityId) {
		try {
			m_ctx = LoginManager.getContextManager().getNamingContext(
					Config.getConfig("Login.USER"),
					Config.getConfig("Login.PASSWORD"), 
					Config.getConfig("Login.URL"));
		} catch (NamingException e) {
			return null;
		}

		NotifyActionInhibitionInfo info = null;
		try {
			// 抑制情報を取得
			try{
				NotifyActionInhibitionInfoHome home = (NotifyActionInhibitionInfoHome) m_ctx
				.lookup(NotifyActionInhibitionInfoHome.JNDI_NAME);

				NotifyActionInhibitionInfoPK inhibitionPk = 
					new NotifyActionInhibitionInfoPK(notifyGroupId, notifyId, facilityId);
				info = home.findByPrimaryKey(inhibitionPk);
			}
			// 存在しない場合
			catch(FinderException e){
			}
			return info;
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
		}
		m_ctx = null;
		return null;
	}

	/**
	 * イベント情報配列 のインスタンスを返します。<br>
	 * 
	 * @param facilityId ファシリティID
	 * @param fromDate 出力日時（開始）
	 * @param toDate 出力日時（終了）
	 * @return イベント情報配列
	 */
	public synchronized ArrayList<ReportEventInfo> getEvent(
			String facilityId, Date fromDate, Date toDate) {

		if(eventList == null){
			eventList = new HashMap<String, ArrayList<ReportEventInfo>>();
			ArrayList<ReportEventInfo> records = getEvent(fromDate, toDate);
			for(ReportEventInfo event : records){
				ArrayList<ReportEventInfo> events = eventList.get(event.getFacilityId());
				if(!(events instanceof ArrayList)){
					events = new ArrayList<ReportEventInfo>();
				}
				events.add(event);
				eventList.put(event.getFacilityId(), events);
			}
		}

		if(eventList instanceof HashMap)
			if(facilityId instanceof String && facilityId.length() > 0)
				return eventList.get(facilityId);
			else{
				Collection<ArrayList<ReportEventInfo>> collection = eventList.values();
				ArrayList<ReportEventInfo> resultList = new ArrayList<ReportEventInfo>();
				for(ArrayList<ReportEventInfo> list : collection){
					resultList.addAll(list);
				}
				return resultList;
			}
		else
			return null;
	}

	/**
	 * イベント情報配列 のインスタンスを返します。<br>
	 * 
	 * @param fromDate 出力日時（開始）
	 * @param toDate 出力日時（終了）
	 * @return イベント情報配列
	 */
	public synchronized ArrayList<ReportEventInfo> getEvent(Date fromDate, Date toDate) {

		MonitorController monitor = EjbConnectionManager.getConnectionManager()
		.getMonitorController();

		ArrayList<ReportEventInfo> records = null;
		try {
			Property filter = monitor.getEventFilterProperty(Locale.getDefault());

			//重要度を設定
			ArrayList properties = PropertyUtil.getProperty(filter, EventFilterProperty.PRIORITY);
			((Property)properties.get(0)).setValue("");

			//出力日時を設定
			if(fromDate instanceof Date){
				properties = PropertyUtil.getProperty(filter, EventFilterProperty.OUTPUT_FROM_DATE);
				((Property)properties.get(0)).setValue(fromDate);
			}

			//出力日時を設定
			if(toDate instanceof Date){
				properties = PropertyUtil.getProperty(filter, EventFilterProperty.OUTPUT_TO_DATE);
				((Property)properties.get(0)).setValue(toDate);
			}

			//確認を設定
			properties = PropertyUtil.getProperty(filter, EventFilterProperty.CONFIRMED);
			((Property)properties.get(0)).setValue("");

			records = monitor.getEventListForReport(null, filter);
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
			System.exit(14);
		}

		return records;
	}

	/**
	 * ステータス情報 EnbtityBean のインスタンスを返します。<br>
	 * 
	 * @param facilityId ファシリティID
	 * @return ステータス情報 EnbtityBean
	 */
	public synchronized ArrayList<StatusInfoData> getStatus(
			String facilityId) {

		MonitorController monitor = EjbConnectionManager.getConnectionManager()
		.getMonitorController();

		ArrayList<StatusInfoData> records = null;
		try {
			records = monitor.getStatusList(facilityId);
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
			System.exit(14);
		}

		return records;
	}

	/**
	 * 通知情報を取得する。<br>
	 * 
	 * @param notifyId 取得対象の通知ID
	 * @return 通知情報
	 */
	public synchronized NotifyInfo getNotifyId(String notifyId) {
		if(notifyList == null){
			NotifyController notify = EjbConnectionManager.getConnectionManager()
			.getNotifyController();

			notifyList = new HashMap<String, NotifyInfo>();
			try {
				ArrayList idList = notify.getNotifyIdList();
				if(idList instanceof ArrayList){
					Iterator itr = idList.iterator();
					while(itr.hasNext()){
						String id = (String)itr.next();
						NotifyInfo info = notify.getNotify(id);
						notifyList.put(id, info);
					}
				}
			} catch (Exception e) {
				notifyList = null;
			}
		}

		if(notifyList instanceof HashMap)
			return notifyList.get(notifyId);
		else
			return null;
	}
}