/*
 
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.export.notify;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;

import jp.co.intellilink.hinemos.export.util.Config;
import jp.co.intellilink.hinemos.export.util.EjbConnectionManager;
import jp.co.intellilink.hinemos.export.util.Messages;
import jp.co.intellilink.hinemos.export.util.StringListComparator;
import jp.co.intellilink.hinemos.export.util.WriteCsvFile;

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

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.ejb.session.NotifyController;

/**
 * 通知情報を取得するクラス<br>
 * 
 * @version 1.0.0
 * @since 1.0.0
 */
public class ExportNotify {
	
	// ログ出力
	private static Log log = LogFactory.getLog(ExportNotify.class);
	
    /**
     * 通知情報をExportする。<br>
     */
    public void exportNotify() {
    	log.info(Messages.getMsg("ExportTool.Nofity.Start"));
    	
    	//CSV出力配列を用意
    	ArrayList<ArrayList<String>> csvStatusOutput = new ArrayList<ArrayList<String>>();
    	ArrayList<ArrayList<String>> csvEventOutput = new ArrayList<ArrayList<String>>();
    	ArrayList<ArrayList<String>> csvMailOutput = new ArrayList<ArrayList<String>>();
    	ArrayList<ArrayList<String>> csvJobOutput = new ArrayList<ArrayList<String>>();
    	ArrayList<ArrayList<String>> csvLogEscalateOutput = new ArrayList<ArrayList<String>>();
    	
    	//通知IDリスト取得
    	ArrayList idList = getNotifyIdList();
    	
    	if(idList instanceof ArrayList){
			Iterator itr = idList.iterator();
			while(itr.hasNext()){
				String id = (String)itr.next();
				
				Object[] args = {id};
				log.info(Messages.getMsg("ExportTool.NotifyID", args));
				
				NotifyInfo info = getNotify(id);
				ArrayList<String> csvFormat = createCsvFormat(info);
				if(info.getNotifyType().intValue() == NotifyTypeConstant.TYPE_STATUS)
					csvStatusOutput.add(csvFormat);
				else if(info.getNotifyType().intValue() == NotifyTypeConstant.TYPE_EVENT)
					csvEventOutput.add(csvFormat);
				else if(info.getNotifyType().intValue() == NotifyTypeConstant.TYPE_MAIL)
					csvMailOutput.add(csvFormat);
				else if(info.getNotifyType().intValue() == NotifyTypeConstant.TYPE_JOB)
					csvJobOutput.add(csvFormat);
				else if(info.getNotifyType().intValue() == NotifyTypeConstant.TYPE_LOG_ESCALATE)
					csvLogEscalateOutput.add(csvFormat);
			}
			
			//通知IDでソート
			Collections.sort(csvStatusOutput, new StringListComparator(0));
			Collections.sort(csvEventOutput, new StringListComparator(0));
			Collections.sort(csvMailOutput, new StringListComparator(0));
			Collections.sort(csvJobOutput, new StringListComparator(0));
			Collections.sort(csvLogEscalateOutput, new StringListComparator(0));
    	}
		
		SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd_HHmmss");
		
		WriteCsvFile.writeCsvFile(
				Config.getConfig("Output.Dir") + "/NOTIFY_STATUS_" + format.format(new Date()) + ".csv", 
				csvStatusOutput);
		WriteCsvFile.writeCsvFile(
				Config.getConfig("Output.Dir") + "/NOTIFY_EVENT_" + format.format(new Date()) + ".csv", 
				csvEventOutput);
		WriteCsvFile.writeCsvFile(
				Config.getConfig("Output.Dir") + "/NOTIFY_MAIL_" + format.format(new Date()) + ".csv", 
				csvMailOutput);
		WriteCsvFile.writeCsvFile(
				Config.getConfig("Output.Dir") + "/NOTIFY_JOB_" + format.format(new Date()) + ".csv", 
				csvJobOutput);
		WriteCsvFile.writeCsvFile(
				Config.getConfig("Output.Dir") + "/NOTIFY_LOG_ESCALATE_" + format.format(new Date()) + ".csv", 
				csvLogEscalateOutput);
		
		log.info(Messages.getMsg("ExportTool.Nofity.End"));
    }
    
    /**
	 * 通知情報をExportする。<br>
	 * 
	 * @param notifyInfo 通知情報
	 * @return CSVフォーマット文字列
	 */
	public ArrayList<String> createCsvFormat(NotifyInfo notifyInfo) {
		ArrayList<String> csvFormat = new ArrayList<String>();
		
		//通知ID
		csvFormat.add(notifyInfo.getNotifyId());
		//説明
		csvFormat.add(notifyInfo.getDescription());
		//抑制方法
		csvFormat.add(ExclusionConstant.typeToString(notifyInfo.getInhibitionFlg()));
		//抑制閾値
		if(notifyInfo.getInhibitionFlg().intValue() == ExclusionConstant.TYPE_FREQUENCY)
			csvFormat.add(notifyInfo.getInhibitionFrequency().toString());
		else if(notifyInfo.getInhibitionFlg().intValue() == ExclusionConstant.TYPE_PERIOD)
			csvFormat.add(notifyInfo.getInhibitionPeriod().toString());
		else
			csvFormat.add("");
		//有効/無効
		csvFormat.add(ValidConstant.typeToString(notifyInfo.getValidFlg()));
		
		if(notifyInfo.getNotifyType().intValue() == NotifyTypeConstant.TYPE_STATUS){
			//ステータス通知
			csvFormat.addAll(createStatusCsvFormat(notifyInfo));
		}
		else if(notifyInfo.getNotifyType().intValue() == NotifyTypeConstant.TYPE_EVENT){
			//イベント通知
			csvFormat.addAll(createEventCsvFormat(notifyInfo));
		}
		else if(notifyInfo.getNotifyType().intValue() == NotifyTypeConstant.TYPE_MAIL){
			//メール通知
			csvFormat.addAll(createMailCsvFormat(notifyInfo));
		}
		else if(notifyInfo.getNotifyType().intValue() == NotifyTypeConstant.TYPE_JOB){
			//ジョブ通知
			csvFormat.addAll(createJobCsvFormat(notifyInfo));
		}
		else if(notifyInfo.getNotifyType().intValue() == NotifyTypeConstant.TYPE_LOG_ESCALATE){
			//ログエスカレーション通知
			csvFormat.addAll(createSyslogCsvFormat(notifyInfo));
		}
		
		return csvFormat;
	}

	/**
     * ステータス通知情報をExportする。<br>
     * 
     * @param notifyInfo 通知情報
     * @return ステータス通知情報CSVフォーマット文字列
     */
	protected ArrayList<String> createStatusCsvFormat(NotifyInfo notifyInfo) {
		ArrayList<String> csvFormat = new ArrayList<String>();
		
		ArrayList<String> status = new ArrayList<String>();
		ArrayList<String> info = new ArrayList<String>();
		ArrayList<String> warning = new ArrayList<String>();
		ArrayList<String> unknown = new ArrayList<String>();
		ArrayList<String> critical = new ArrayList<String>();
		
		//ステータス通知
		if(notifyInfo.getNotifyType().intValue() == NotifyTypeConstant.TYPE_STATUS){
			ArrayList<NotifyInfoDetail> details = notifyInfo.getNotifyInfoDetail();
			
			for (NotifyInfoDetail detail : details) {
				ArrayList<String> priority = null;
				if(detail.getPriority() == PriorityConstant.TYPE_INFO){
					priority = info;
					NotifyStatusInfo statusInfo = (NotifyStatusInfo)detail;
	    			//ステータス情報の存続期間
					status.add(StatusValidPeriodConstant.typeToString(statusInfo.getStatusValidPeriod().intValue()));
	    			//存続期間経過後の処理：方法
	    			if(statusInfo.getStatusInvalidFlg().intValue() == StatusExpirationConstant.TYPE_DELETE)
	    				status.add(com.clustercontrol.util.Messages.getString("notify.status.invalid.period.delete"));
	    			else
	    				status.add(com.clustercontrol.util.Messages.getString("notify.status.invalid.period.updatet"));
	    			//存続期間経過後の処理：重要度
	    			status.add(PriorityConstant.typeToString(statusInfo.getStatusUpdatePriority()));
				}
				else if(detail.getPriority() == PriorityConstant.TYPE_WARNING)
					priority = warning;
				else if(detail.getPriority() == PriorityConstant.TYPE_UNKNOWN)
					priority = unknown;
				else if(detail.getPriority() == PriorityConstant.TYPE_CRITICAL)
					priority = critical;
				//通知
				priority.add(ValidConstant.typeToString(detail.getValidFlg()));
				//抑制
				priority.add(ValidConstant.typeToString(detail.getInhibitionFlg()));
			}
		}
		else{
			for(int i=0; i < 3; i++)
				status.add("");
	
			for(int i=0; i < 2; i++){
				info.add("");
				warning.add("");
				critical.add("");
				unknown.add("");
			}
		}
		
		csvFormat.addAll(info);
		csvFormat.addAll(warning);
		csvFormat.addAll(critical);
		csvFormat.addAll(unknown);
		csvFormat.addAll(status);
		
		return csvFormat;
	}

	/**
	 * イベント通知情報をExportする。<br>
	 * 
	 * @param notifyInfo 通知情報
	 * @return イベント通知情報CSVフォーマット文字列
	 */
	protected ArrayList<String> createEventCsvFormat(NotifyInfo notifyInfo) {
		ArrayList<String> csvFormat = new ArrayList<String>();
		
		ArrayList<String> info = new ArrayList<String>();
		ArrayList<String> warning = new ArrayList<String>();
		ArrayList<String> unknown = new ArrayList<String>();
		ArrayList<String> critical = new ArrayList<String>();
		
		//イベント通知
		if(notifyInfo.getNotifyType().intValue() == NotifyTypeConstant.TYPE_EVENT){
			ArrayList<NotifyInfoDetail> details = notifyInfo.getNotifyInfoDetail();
			
			for (NotifyInfoDetail detail : details) {
				ArrayList<String> priority = null;
				NotifyEventInfo eventInfo = (NotifyEventInfo)detail;
				if(detail.getPriority() == PriorityConstant.TYPE_INFO)
					priority = info;
				else if(detail.getPriority() == PriorityConstant.TYPE_WARNING)
					priority = warning;
				else if(detail.getPriority() == PriorityConstant.TYPE_UNKNOWN)
					priority = unknown;
				else if(detail.getPriority() == PriorityConstant.TYPE_CRITICAL)
					priority = critical;
				//通知
				priority.add(ValidConstant.typeToString(eventInfo.getValidFlg()));
				//状態
				priority.add(EventConfirmConstant.typeToString(eventInfo.getEventNormalState()));
				//抑制
				priority.add(ValidConstant.typeToString(eventInfo.getInhibitionFlg()));
				//状態
				priority.add(EventConfirmConstant.typeToString(eventInfo.getEventInhibitionState()));
			}
		}
		else{
			for(int i=0; i < 4; i++){
				info.add("");
				warning.add("");
				critical.add("");
				unknown.add("");
			}
		}
		
		csvFormat.addAll(info);
		csvFormat.addAll(warning);
		csvFormat.addAll(critical);
		csvFormat.addAll(unknown);
		
		return csvFormat;
	}

	/**
	 * メール通知情報をExportする。<br>
	 * 
	 * @param notifyInfo 通知情報
	 * @return メール通知情報CSVフォーマット文字列
	 */
	protected ArrayList<String> createMailCsvFormat(NotifyInfo notifyInfo) {
		ArrayList<String> csvFormat = new ArrayList<String>();
		
		ArrayList<String> mail = new ArrayList<String>();
		ArrayList<String> info = new ArrayList<String>();
		ArrayList<String> warning = new ArrayList<String>();
		ArrayList<String> unknown = new ArrayList<String>();
		ArrayList<String> critical = new ArrayList<String>();
		
		//メール通知
		if(notifyInfo.getNotifyType().intValue() == NotifyTypeConstant.TYPE_MAIL){
			ArrayList<NotifyInfoDetail> details = notifyInfo.getNotifyInfoDetail();
			
			for (NotifyInfoDetail detail : details) {
				ArrayList<String> priority = null;
				NotifyMailInfo mailInfo = (NotifyMailInfo)detail;
				if(detail.getPriority() == PriorityConstant.TYPE_INFO){
					priority = info;
	                //通知のみメール通知の共通部分の設定行う
	                if (mailInfo.getMailTemplateId() != null) 
	                	mail.add(mailInfo.getMailTemplateId());
	                else
	                	mail.add("");
				}
				else if(detail.getPriority() == PriorityConstant.TYPE_WARNING)
					priority = warning;
				else if(detail.getPriority() == PriorityConstant.TYPE_UNKNOWN)
					priority = unknown;
				else if(detail.getPriority() == PriorityConstant.TYPE_CRITICAL)
					priority = critical;
				//通知
				priority.add(ValidConstant.typeToString(mailInfo.getValidFlg()));
				//メールアドレス
				if (mailInfo.getMailAddress() != null) 
					priority.add(mailInfo.getMailAddress());
				else
					priority.add("");
				//抑制
				priority.add(ValidConstant.typeToString(mailInfo.getInhibitionFlg()));
			}
		}
		else{
			mail.add("");
			
			for(int i=0; i < 3; i++){
				info.add("");
				warning.add("");
				critical.add("");
				unknown.add("");
			}
		}
		
		csvFormat.addAll(mail);
		csvFormat.addAll(info);
		csvFormat.addAll(warning);
		csvFormat.addAll(critical);
		csvFormat.addAll(unknown);
		
		return csvFormat;
	}

	/**
	 * ジョブ通知情報をExportする。<br>
	 * 
	 * @param notifyInfo 通知情報
	 * @return ジョブ通知情報CSVフォーマット文字列
	 */
	protected ArrayList<String> createJobCsvFormat(NotifyInfo notifyInfo) {
		ArrayList<String> csvFormat = new ArrayList<String>();
		
		ArrayList<String> job = new ArrayList<String>();
		ArrayList<String> info = new ArrayList<String>();
		ArrayList<String> warning = new ArrayList<String>();
		ArrayList<String> unknown = new ArrayList<String>();
		ArrayList<String> critical = new ArrayList<String>();
		
		//ジョブ通知
		if(notifyInfo.getNotifyType().intValue() == NotifyTypeConstant.TYPE_JOB){
			ArrayList<NotifyInfoDetail> details = notifyInfo.getNotifyInfoDetail();
			
			for (NotifyInfoDetail detail : details) {
				ArrayList<String> priority = null;
				NotifyJobInfo jobInfo = (NotifyJobInfo)detail;
				if(detail.getPriority() == PriorityConstant.TYPE_INFO){
					priority = info;
					//ジョブ実行スコープ
					if (jobInfo.getJobExecFacilityFlg() != null && 
							jobInfo.getJobExecFacilityFlg() == ExecFacilityConstant.TYPE_GENERATION)
						job.add(com.clustercontrol.util.Messages.getString("notify.node.generation"));
					else 
						job.add(com.clustercontrol.util.Messages.getString("notify.node.fix"));
					//ファシリティID
					if (jobInfo.getJobExecFacility() != null) 
						job.add(jobInfo.getJobExecFacility());
					else
						job.add("");
				}
				else if(detail.getPriority() == PriorityConstant.TYPE_WARNING)
					priority = warning;
				else if(detail.getPriority() == PriorityConstant.TYPE_UNKNOWN)
					priority = unknown;
				else if(detail.getPriority() == PriorityConstant.TYPE_CRITICAL)
					priority = critical;
				//通知
				priority.add(ValidConstant.typeToString(jobInfo.getValidFlg()));
				//ジョブID
				if (jobInfo.getJobId() != null) 
					priority.add(jobInfo.getJobId());
				else
					priority.add("");
				//抑制
				priority.add(ValidConstant.typeToString(jobInfo.getInhibitionFlg()));
				//状態
				priority.add(PriorityConstant.typeToString(jobInfo.getJobFailurePriority()));
			}
		}
		else{
			for(int i=0; i < 2; i++)
				job.add("");
			
			for(int i=0; i < 4; i++){
				info.add("");
				warning.add("");
				critical.add("");
				unknown.add("");
			}
		}
		
		csvFormat.addAll(job);
		csvFormat.addAll(info);
		csvFormat.addAll(warning);
		csvFormat.addAll(critical);
		csvFormat.addAll(unknown);
		
		return csvFormat;
	}

	/**
     * ログエスカレーション通知情報をExportする。<br>
     * 
     * @param notifyInfo 通知情報
     * @return ログエスカレーション通知情報CSVフォーマット文字列
     */
	protected ArrayList<String> createSyslogCsvFormat(NotifyInfo notifyInfo) {
    	ArrayList<String> csvFormat = new ArrayList<String>();
    	
    	ArrayList<String> syslog = new ArrayList<String>();
		ArrayList<String> info = new ArrayList<String>();
		ArrayList<String> warning = new ArrayList<String>();
		ArrayList<String> unknown = new ArrayList<String>();
		ArrayList<String> critical = new ArrayList<String>();
		
    	//ログエスカレーション通知
    	if(notifyInfo.getNotifyType().intValue() == NotifyTypeConstant.TYPE_LOG_ESCALATE){
    		ArrayList<NotifyInfoDetail> details = notifyInfo.getNotifyInfoDetail();
    		
    		for (NotifyInfoDetail detail : details) {
    			ArrayList<String> priority = null;
    			NotifyLogEscalateInfo syslogInfo = (NotifyLogEscalateInfo)detail;
    			if(detail.getPriority() == PriorityConstant.TYPE_INFO){
    				priority = info;
					//ログエスカレーションスコープ
					if (syslogInfo.getEscalateFacilityFlg() != null && 
							syslogInfo.getEscalateFacilityFlg() == ExecFacilityConstant.TYPE_GENERATION)
						syslog.add(com.clustercontrol.util.Messages.getString("notify.node.generation"));
					else 
						syslog.add(com.clustercontrol.util.Messages.getString("notify.node.fix"));
					//ファシリティID
					if (syslogInfo.getEscalateFacility() != null) 
						syslog.add(syslogInfo.getEscalateFacility());
					else
						syslog.add("");
					//ポート番号
					syslog.add(syslogInfo.getEscalatePort().toString());
    			}
    			else if(detail.getPriority() == PriorityConstant.TYPE_WARNING)
    				priority = warning;
    			else if(detail.getPriority() == PriorityConstant.TYPE_UNKNOWN)
    				priority = unknown;
    			else if(detail.getPriority() == PriorityConstant.TYPE_CRITICAL)
    				priority = critical;
    			//通知
    			priority.add(ValidConstant.typeToString(syslogInfo.getValidFlg()));
    			//Facility
    			priority.add(SyslogFacilityConstant.typeToString(syslogInfo.getSyslogFacility()));
    			//Severity
    			priority.add(SyslogSeverityConstant.typeToString(syslogInfo.getSyslogPriority()));
				//メッセージ
				if (syslogInfo.getEscalateMessage() != null) 
					priority.add(syslogInfo.getEscalateMessage());
				else
					priority.add("");
    			//抑制
    			priority.add(ValidConstant.typeToString(syslogInfo.getInhibitionFlg()));
    		}
    	}
    	else{
    		for(int i=0; i < 3; i++)
    			syslog.add("");
    		
    		for(int i=0; i < 5; i++){
    			info.add("");
    			warning.add("");
    			critical.add("");
    			unknown.add("");
    		}
    	}
    	
    	csvFormat.addAll(syslog);
		csvFormat.addAll(info);
		csvFormat.addAll(warning);
		csvFormat.addAll(critical);
		csvFormat.addAll(unknown);
    	
    	return csvFormat;
    }
	
    /**
     * 通知情報を取得する。<br>
     * 
     * @param notifyId 取得対象の通知ID
     * @return 通知情報
     */
    protected NotifyInfo getNotify(String notifyId) {

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

        NotifyInfo info = null;
        try {
        	info = notify.getNotify(notifyId);
        } catch (Exception e) {
			log.error(Messages.getMsg("ExportTool.ConnectManagerFailed"), e);
			System.exit(14);
        }
        return info;
    }
    
    /**
     * 通知IDリストを取得する。<br>
     * 
     * @return 通知ID一覧
     */
    protected ArrayList getNotifyIdList() {

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

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