/*

Copyright (C) 2009 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.importtool.conf.notify;

import java.util.ArrayList;
import java.util.Iterator;

import javax.ejb.DuplicateKeyException;

import jp.co.intellilink.hinemos.util.CheckString;
import jp.co.intellilink.hinemos.util.Config;
import jp.co.intellilink.hinemos.util.EjbConnectionManager;
import jp.co.intellilink.hinemos.util.MailTemplateUtil;
import jp.co.intellilink.hinemos.util.Messages;
import jp.co.intellilink.hinemos.util.ReadCsvFile;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.clustercontrol.bean.DataRangeConstant;
import com.clustercontrol.bean.EventConfirmConstant;
import com.clustercontrol.bean.ExclusionConstant;
import com.clustercontrol.bean.ExecFacilityConstant;
import com.clustercontrol.bean.NotifyTypeConstant;
import com.clustercontrol.bean.PriorityConstant;
import com.clustercontrol.bean.StatusExpirationConstant;
import com.clustercontrol.bean.StatusValidPeriodConstant;
import com.clustercontrol.bean.SyslogFacilityConstant;
import com.clustercontrol.bean.SyslogSeverityConstant;
import com.clustercontrol.bean.ValidConstant;
import com.clustercontrol.notify.bean.NotifyEventInfo;
import com.clustercontrol.notify.bean.NotifyInfo;
import com.clustercontrol.notify.bean.NotifyInfoDetail;
import com.clustercontrol.notify.bean.NotifyJobInfo;
import com.clustercontrol.notify.bean.NotifyLogEscalateInfo;
import com.clustercontrol.notify.bean.NotifyMailInfo;
import com.clustercontrol.notify.bean.NotifyStatusInfo;
import com.clustercontrol.notify.bean.NotifyTableDefine;
import com.clustercontrol.notify.ejb.session.NotifyController;

/**
 * 通知情報をインポートするクラス<br>
 * 
 * @version 1.0.0
 * @since 1.0.0
 */
public class ImportNotify {

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

	@SuppressWarnings("unchecked")
	private ArrayList notifyList = null;

	private ArrayList<ArrayList<String>> notifyStatusInfos = null;
	private ArrayList<ArrayList<String>> notifyEventInfos = null;
	private ArrayList<ArrayList<String>> notifyMailInfos = null;
	private ArrayList<ArrayList<String>> notifyJobInfos = null;
	private ArrayList<ArrayList<String>> notifyLogEscalateInfos = null;

	/**
	 * 通知情報をインポートする。<br>
	 */
	public void importNotify() {
		log.info(Messages.getMsg("Nofity.Start", new String[]{Messages.getMsg("ImportTool.Import")}));

		//ステータス通知情報のCSVファイルを読み込む
		notifyStatusInfos = ReadCsvFile.readCsvFile(Config.getConfig("Import.Dir") + "/NOTIFY_STATUS.csv");
		//イベント通知情報のCSVファイルを読み込む
		notifyEventInfos = ReadCsvFile.readCsvFile(Config.getConfig("Import.Dir") + "/NOTIFY_EVENT.csv");
		//メール通知情報のCSVファイルを読み込む
		notifyMailInfos = ReadCsvFile.readCsvFile(Config.getConfig("Import.Dir") + "/NOTIFY_MAIL.csv");
		//ジョブ通知情報のCSVファイルを読み込む
		notifyJobInfos = ReadCsvFile.readCsvFile(Config.getConfig("Import.Dir") + "/NOTIFY_JOB.csv");
		//ログエスカレーション通知情報のCSVファイルを読み込む
		notifyLogEscalateInfos = ReadCsvFile.readCsvFile(Config.getConfig("Import.Dir") + "/NOTIFY_LOG_ESCALATE.csv");

		//通知リスト取得
		notifyList = getNotifyList();

		//ステータス通知
		for(ArrayList<String> info : notifyStatusInfos){
			NotifyInfo notifyInfo = createNotifyInfo(info, NotifyTypeConstant.TYPE_STATUS);
			registerNotifyInfo(notifyInfo);
		}

		//イベント通知
		for(ArrayList<String> info : notifyEventInfos){
			NotifyInfo notifyInfo = createNotifyInfo(info, NotifyTypeConstant.TYPE_EVENT);
			registerNotifyInfo(notifyInfo);
		}

		//メール通知
		for(ArrayList<String> info : notifyMailInfos){
			NotifyInfo notifyInfo = createNotifyInfo(info, NotifyTypeConstant.TYPE_MAIL);
			registerNotifyInfo(notifyInfo);
		}

		//ジョブ通知
		for(ArrayList<String> info : notifyJobInfos){
			NotifyInfo notifyInfo = createNotifyInfo(info, NotifyTypeConstant.TYPE_JOB);
			registerNotifyInfo(notifyInfo);
		}

		//ログエスカレーション通知
		for(ArrayList<String> info : notifyLogEscalateInfos){
			NotifyInfo notifyInfo = createNotifyInfo(info, NotifyTypeConstant.TYPE_LOG_ESCALATE);
			registerNotifyInfo(notifyInfo);
		}

		log.info(Messages.getMsg("Nofity.End", new String[]{Messages.getMsg("ImportTool.Import")}));
	}

	/**
	 * 通知情報を作成する。<br>
	 * 
	 * @param info 通知情報配列
	 * @return 通知情報
	 */
	public NotifyInfo createNotifyInfo(ArrayList<String> info, int notifyType) {
		NotifyInfo notifyInfo = new NotifyInfo();

		//通知ID
		String id = CheckString.checkLength(info.get(0), DataRangeConstant.VARCHAR_64);
		if(!id.equals(info.get(0))){
			String[] args = { com.clustercontrol.util.Messages.getString("notify.id"), "64" };
			log.error(Messages.getMsg("ImportTool.Common.2", args));
			System.exit(20);
		}
		notifyInfo.setNotifyId(id);
		//説明
		String description = CheckString.checkLength(info.get(1), DataRangeConstant.VARCHAR_256);
		if(!description.equals(info.get(1))){
			String[] args = { com.clustercontrol.util.Messages.getString("description"), "256" };
			log.warn(Messages.getMsg("ImportTool.Common.2", args));
		}
		notifyInfo.setDescription(description);
		//抑制方法
		notifyInfo.setInhibitionFlg(ExclusionConstant.stringToType(info.get(2)));
		//抑制閾値
		if(notifyInfo.getInhibitionFlg().intValue() == ExclusionConstant.TYPE_FREQUENCY)
			notifyInfo.setInhibitionFrequency(Integer.parseInt(info.get(3)));
		else if(notifyInfo.getInhibitionFlg().intValue() == ExclusionConstant.TYPE_PERIOD)
			notifyInfo.setInhibitionPeriod(Integer.parseInt(info.get(3)));
		//有効/無効
		notifyInfo.setValidFlg(ValidConstant.stringToType(info.get(4)));

		//通知種別
		notifyInfo.setNotifyType(notifyType);
		if(notifyInfo.getNotifyType().intValue() == NotifyTypeConstant.TYPE_STATUS){
			//ステータス通知
			createStatusNotifyInfo(info, notifyInfo);
		}
		else if(notifyInfo.getNotifyType().intValue() == NotifyTypeConstant.TYPE_EVENT){
			//イベント通知
			createEventNotifyInfo(info, notifyInfo);
		}
		else if(notifyInfo.getNotifyType().intValue() == NotifyTypeConstant.TYPE_MAIL){
			//メール通知
			createMailNotifyInfo(info, notifyInfo);
		}
		else if(notifyInfo.getNotifyType().intValue() == NotifyTypeConstant.TYPE_JOB){
			//ジョブ通知
			createJobNotifyInfo(info, notifyInfo);
		}
		else if(notifyInfo.getNotifyType().intValue() == NotifyTypeConstant.TYPE_LOG_ESCALATE){
			//ログエスカレーション通知
			createSyslogNotifyInfo(info, notifyInfo);
		}

		return notifyInfo;
	}

	/**
	 * ステータス通知情報を設定する。<br>
	 * 
	 * @param info 通知情報配列
	 * @param notifyInfo 通知情報
	 */
	protected void createStatusNotifyInfo(ArrayList<String> info, NotifyInfo notifyInfo) {
		ArrayList<NotifyInfoDetail> details = new ArrayList<NotifyInfoDetail>();

		//ステータス情報の存続期間
		int validPeriod = StatusValidPeriodConstant.stringToType(info.get(13));
		//存続期間経過後の処理：方法
		int invalidFlg = StatusExpirationConstant.TYPE_DELETE;
		if(info.get(14).equals(com.clustercontrol.util.Messages.getString("notify.status.invalid.period.delete")))
			invalidFlg = StatusExpirationConstant.TYPE_DELETE;
		else
			invalidFlg = StatusExpirationConstant.TYPE_UPDATE;
		//存続期間経過後の処理：重要度
		int updatePriority = PriorityConstant.stringToType(info.get(15));

		for(int i = 0; i < 4; i++){
			NotifyStatusInfo statusInfo = new NotifyStatusInfo();
			statusInfo.setNotifyId(notifyInfo.getNotifyId());

			//重要度
			if(i == 0)
				statusInfo.setPriority(PriorityConstant.TYPE_INFO);
			else if(i == 1)
				statusInfo.setPriority(PriorityConstant.TYPE_WARNING);
			else if(i == 2)
				statusInfo.setPriority(PriorityConstant.TYPE_CRITICAL);
			else if(i == 3)
				statusInfo.setPriority(PriorityConstant.TYPE_UNKNOWN);
			//通知
			statusInfo.setValidFlg(ValidConstant.stringToType(info.get(i * 2 + 5)));
			//抑制
			statusInfo.setInhibitionFlg(ValidConstant.stringToType(info.get(i * 2 + 6)));
			//ステータス情報の存続期間
			statusInfo.setStatusValidPeriod(validPeriod);
			//存続期間経過後の処理：方法
			statusInfo.setStatusInvalidFlg(invalidFlg);
			//存続期間経過後の処理：重要度
			statusInfo.setStatusUpdatePriority(updatePriority);

			details.add(statusInfo);
		}
		notifyInfo.setNotifyInfoDetail(details);
	}

	/**
	 * イベント通知情報を設定する。<br>
	 * 
	 * @param info 通知情報配列
	 * @param notifyInfo 通知情報
	 */
	protected void createEventNotifyInfo(ArrayList<String> info, NotifyInfo notifyInfo) {
		ArrayList<NotifyInfoDetail> details = new ArrayList<NotifyInfoDetail>();

		for(int i = 0; i < 4; i++){
			NotifyEventInfo eventInfo = new NotifyEventInfo();
			eventInfo.setNotifyId(notifyInfo.getNotifyId());

			//重要度
			if(i == 0)
				eventInfo.setPriority(PriorityConstant.TYPE_INFO);
			else if(i == 1)
				eventInfo.setPriority(PriorityConstant.TYPE_WARNING);
			else if(i == 2)
				eventInfo.setPriority(PriorityConstant.TYPE_CRITICAL);
			else if(i == 3)
				eventInfo.setPriority(PriorityConstant.TYPE_UNKNOWN);
			//通知
			eventInfo.setValidFlg(ValidConstant.stringToType(info.get(i * 4 + 5)));
			//状態
			eventInfo.setEventNormalState(EventConfirmConstant.stringToType(info.get(i * 4 + 6)));
			//抑制
			eventInfo.setInhibitionFlg(ValidConstant.stringToType(info.get(i * 4 + 7)));
			//状態
			eventInfo.setEventInhibitionState(EventConfirmConstant.stringToType(info.get(i * 4 + 8)));

			details.add(eventInfo);
		}
		notifyInfo.setNotifyInfoDetail(details);
	}

	/**
	 * メール通知情報を設定する。<br>
	 * 
	 * @param info 通知情報配列
	 * @param notifyInfo 通知情報
	 */
	protected void createMailNotifyInfo(ArrayList<String> info, NotifyInfo notifyInfo) {
		ArrayList<NotifyInfoDetail> details = new ArrayList<NotifyInfoDetail>();

		//メールテンプレートID
		String mailTemplateId = info.get(5);
		if(!MailTemplateUtil.findMailTemplateId(mailTemplateId)){
			String args[] = {notifyInfo.getNotifyId(), mailTemplateId};
			log.error(Messages.getMsg("ImportTool.MailTemplate.1", args));
			System.exit(20);
		}

		for(int i = 0; i < 4; i++){
			NotifyMailInfo mailInfo = new NotifyMailInfo();
			mailInfo.setNotifyId(notifyInfo.getNotifyId());

			//重要度
			if(i == 0)
				mailInfo.setPriority(PriorityConstant.TYPE_INFO);
			else if(i == 1)
				mailInfo.setPriority(PriorityConstant.TYPE_WARNING);
			else if(i == 2)
				mailInfo.setPriority(PriorityConstant.TYPE_CRITICAL);
			else if(i == 3)
				mailInfo.setPriority(PriorityConstant.TYPE_UNKNOWN);
			//通知
			mailInfo.setValidFlg(ValidConstant.stringToType(info.get(i * 3 + 6)));
			//メールアドレス
			String mailAddress = CheckString.checkLength(info.get(i * 3 + 7), DataRangeConstant.VARCHAR_1024);
			if(!mailAddress.equals(info.get(i * 3 + 7))){
				String[] args = { com.clustercontrol.util.Messages.getString("email.address.ssv"), "1024" };
				log.warn(Messages.getMsg("ImportTool.Common.2", args));
			}
			mailInfo.setMailAddress(mailAddress);
			//抑制
			mailInfo.setInhibitionFlg(ValidConstant.stringToType(info.get(i * 3 + 8)));
			//メールテンプレートID
			mailInfo.setMailTemplateId(mailTemplateId);

			details.add(mailInfo);
		}
		notifyInfo.setNotifyInfoDetail(details);
	}

	/**
	 * ジョブ通知情報を設定する。<br>
	 * 
	 * @param info 通知情報配列
	 * @param notifyInfo 通知情報
	 */
	protected void createJobNotifyInfo(ArrayList<String> info, NotifyInfo notifyInfo) {
		ArrayList<NotifyInfoDetail> details = new ArrayList<NotifyInfoDetail>();

		//ジョブ実行スコープ
		int execFacilityFlg = ExecFacilityConstant.TYPE_GENERATION;
		if(info.get(5).equals(com.clustercontrol.util.Messages.getString("notify.node.generation")))
			execFacilityFlg = ExecFacilityConstant.TYPE_GENERATION;
		else
			execFacilityFlg = ExecFacilityConstant.TYPE_FIX;
		//ファシリティID
		String execFacility = info.get(6);

		for(int i = 0; i < 4; i++){
			NotifyJobInfo jobInfo = new NotifyJobInfo();
			jobInfo.setNotifyId(notifyInfo.getNotifyId());

			//重要度
			if(i == 0)
				jobInfo.setPriority(PriorityConstant.TYPE_INFO);
			else if(i == 1)
				jobInfo.setPriority(PriorityConstant.TYPE_WARNING);
			else if(i == 2)
				jobInfo.setPriority(PriorityConstant.TYPE_CRITICAL);
			else if(i == 3)
				jobInfo.setPriority(PriorityConstant.TYPE_UNKNOWN);
			//通知
			jobInfo.setValidFlg(ValidConstant.stringToType(info.get(i * 4 + 7)));
			//ジョブID
			jobInfo.setJobId(info.get(i * 4 + 8));
			//抑制
			jobInfo.setInhibitionFlg(ValidConstant.stringToType(info.get(i * 4 + 9)));
			//呼出失敗時
			jobInfo.setJobFailurePriority(PriorityConstant.stringToType(info.get(i * 4 + 10)));
			//ジョブ実行スコープ
			jobInfo.setJobExecFacilityFlg(execFacilityFlg);
			//ファシリティID
			jobInfo.setJobExecFacility(execFacility);

			details.add(jobInfo);
		}
		notifyInfo.setNotifyInfoDetail(details);
	}

	/**
	 * ログエスカレーション通知情報を設定する。<br>
	 * 
	 * @param info 通知情報配列
	 * @param notifyInfo 通知情報
	 */
	protected void createSyslogNotifyInfo(ArrayList<String> info, NotifyInfo notifyInfo) {
		ArrayList<NotifyInfoDetail> details = new ArrayList<NotifyInfoDetail>();

		//ジョブ実行スコープ
		int escalateFacilityFlg = ExecFacilityConstant.TYPE_GENERATION;
		if(info.get(5).equals(com.clustercontrol.util.Messages.getString("notify.node.generation")))
			escalateFacilityFlg = ExecFacilityConstant.TYPE_GENERATION;
		else
			escalateFacilityFlg = ExecFacilityConstant.TYPE_FIX;
		//ファシリティID
		String escalateFacility = info.get(6);
		//ポート番号
		int escalatePort = Integer.parseInt(info.get(7));

		for(int i = 0; i < 4; i++){
			NotifyLogEscalateInfo syslogInfo = new NotifyLogEscalateInfo();
			syslogInfo.setNotifyId(notifyInfo.getNotifyId());

			//重要度
			if(i == 0)
				syslogInfo.setPriority(PriorityConstant.TYPE_INFO);
			else if(i == 1)
				syslogInfo.setPriority(PriorityConstant.TYPE_WARNING);
			else if(i == 2)
				syslogInfo.setPriority(PriorityConstant.TYPE_CRITICAL);
			else if(i == 3)
				syslogInfo.setPriority(PriorityConstant.TYPE_UNKNOWN);
			//通知
			syslogInfo.setValidFlg(ValidConstant.stringToType(info.get(i * 5 + 8)));
			//Facility
			syslogInfo.setSyslogFacility(SyslogFacilityConstant.stringToType(info.get(i * 5 + 9)));
			//Severity
			syslogInfo.setSyslogPriority(SyslogSeverityConstant.stringToType(info.get(i * 5 + 10)));
			//メッセージ
			String message = CheckString.checkLength(info.get(i * 5 + 11), DataRangeConstant.VARCHAR_1024);
			if(!message.equals(info.get(i * 5 + 11))){
				String[] args = { com.clustercontrol.util.Messages.getString("message"), "1024" };
				log.warn(Messages.getMsg("ImportTool.Common.2", args));
			}
			syslogInfo.setEscalateMessage(message);
			//抑制
			syslogInfo.setInhibitionFlg(ValidConstant.stringToType(info.get(i * 5 + 12)));
			//ジョブ実行スコープ
			syslogInfo.setEscalateFacilityFlg(escalateFacilityFlg);
			//ファシリティID
			syslogInfo.setEscalateFacility(escalateFacility);
			//ポート番号
			syslogInfo.setEscalatePort(escalatePort);

			details.add(syslogInfo);
		}
		notifyInfo.setNotifyInfoDetail(details);
	}

	/**
	 * 通知一覧に指定した通知IDが存在するかチェックする。<br>
	 * 
	 * @param notifyId 通知ID
	 * @return チェック結果
	 */
	@SuppressWarnings("unchecked")
	protected ArrayList checkNotifyList(String notifyId) {

		if(notifyList instanceof ArrayList){
			Iterator itr = notifyList.iterator();
			while(itr.hasNext()){
				ArrayList line = (ArrayList)itr.next();

				String id = (String)line.get(NotifyTableDefine.NOTIFY_ID);
				if(id.compareTo(notifyId) == 0)
					return line;
			}
		}

		return null;
	}

	/**
	 * 通知情報を登録する。<br>
	 * 
	 * @param notifyInfo 通知情報
	 */
	protected void registerNotifyInfo(NotifyInfo notifyInfo) {

		NotifyController notify = EjbConnectionManager.getConnectionManager().getNotifyController();

		try {
			@SuppressWarnings("unchecked")
			ArrayList line = checkNotifyList(notifyInfo.getNotifyId());
			if(line instanceof ArrayList){
				Object[] args = {notifyInfo.getNotifyId()};
				log.info(Messages.getMsg("NotifyID", args) + 
						" (" + Messages.getMsg("modify") + ")");

				notify.modifyNotify(notifyInfo);
			}
			else{
				Object[] args = {notifyInfo.getNotifyId()};
				log.info(Messages.getMsg("NotifyID", args) + 
						" (" + Messages.getMsg("add") + ")");

				notify.addNotify(notifyInfo);
			}
		} catch (DuplicateKeyException e) {
			String args[] = {notifyInfo.getNotifyId()};
			log.error(Messages.getMsg("ImportTool.Common.1", args));
			System.exit(20);
		} catch (Exception e) {
			log.error(Messages.getMsg("ConnectManagerFailed"), e);
			System.exit(14);
		}
	}

	/**
	 * 通知リストを取得する。<br>
	 * 
	 * @return 通知一覧
	 */
	@SuppressWarnings("unchecked")
	protected ArrayList getNotifyList() {

		NotifyController notify = EjbConnectionManager.getConnectionManager().getNotifyController();

		ArrayList records = null;
		try {
			records = notify.getNotifyList();
		} catch (Exception e) {
			log.error(Messages.getMsg("ConnectManagerFailed"), e);
			System.exit(14);
		}
		return records;
	}
}