/*

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.test.job;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Locale;

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

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

import com.clustercontrol.bean.JobConstant;
import com.clustercontrol.bean.PriorityConstant;
import com.clustercontrol.jobmanagement.bean.JobInfo;
import com.clustercontrol.jobmanagement.bean.JobTreeItem;
import com.clustercontrol.jobmanagement.ejb.session.JobController;
import com.clustercontrol.monitor.bean.ReportEventInfo;

/**
 * ジョブ実行結果をチェックするクラス<br>
 * 
 * @version 1.1.0
 * @since 1.1.0
 */
public class CheckResultJob {
	private Date fromDate;
	private Date toDate;

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

	public CheckResultJob(Date fromDate, Date toDate){
		this.fromDate = fromDate;
		this.toDate = toDate;
	}

	/**
	 * ジョブ実行結果をチェックする。<br>
	 */
	@SuppressWarnings("unchecked")
	public void checkResult() {
		log.info("[" + Messages.getMsg("CheckResult")+ "] " + Messages.getMsg("TestTool.Job.Start"));

		//ジョブツリー取得
		JobTreeItem jobTree = getJobTree();

		//ジョブ情報のCSV文字列を作成
		ArrayList<ArrayList<String>> csvOutput = new ArrayList<ArrayList<String>>();
		getJobData(jobTree, csvOutput);
		//ジョブIDでソート
		Collections.sort(csvOutput, new StringListComparator(0));

		SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd_HHmmss");
		WriteCsvFile.writeCsvFile(
				Config.getConfig("Check.Output.Dir") + "/JOB_" + format.format(new Date()) + ".csv", 
				csvOutput);

		log.info("[" + Messages.getMsg("CheckResult")+ "] " + Messages.getMsg("TestTool.Job.End"));
	}

	/**
	 * ジョブ情報取得（再帰呼び出し）
	 * 
	 * @param treeItem ジョブツリー
	 * @param csvOutput CSV出力文字列配列
	 */
	public void getJobData(JobTreeItem treeItem, ArrayList<ArrayList<String>> csvOutput) {

		//子ツリーを取得する
		if (treeItem.getData() instanceof JobInfo){
			JobInfo info = treeItem.getData();
			if(info.getId() != null && info.getId().compareTo("") != 0){
				Object[] args = {info.getId()};
				log.info(Messages.getMsg("TestTool.JobID", args));

				csvOutput.add(createCsvFormat(info));
			}
		}

		JobTreeItem[] childrenTreeItem = treeItem.getChildren();
		for (JobTreeItem childTreeItem : childrenTreeItem) {
			getJobData(childTreeItem, csvOutput);
		}
	}

	/**
	 * ジョブ情報からCSV文字列を作成する。<br>
	 * 
	 * @param jobInfo ジョブ情報
	 * @return CSVフォーマット文字列
	 */
	@SuppressWarnings("unchecked")
	public ArrayList<String> createCsvFormat(JobInfo jobInfo) {
		ArrayList<String> csvFormat = new ArrayList<String>();

		//ジョブID
		csvFormat.add(jobInfo.getId());
		//ジョブ名
		csvFormat.add(jobInfo.getName());
		//ジョブ種別
		csvFormat.add(JobConstant.typeToString(jobInfo.getType()));
		//正常
		csvFormat.addAll(checkEventByPriority(
				jobInfo, PriorityConstant.TYPE_INFO, fromDate, toDate));
		//警告
		csvFormat.addAll(checkEventByPriority(
				jobInfo, PriorityConstant.TYPE_WARNING, fromDate, toDate));
		//危険
		csvFormat.addAll(checkEventByPriority(
				jobInfo, PriorityConstant.TYPE_CRITICAL, fromDate, toDate));

		return csvFormat;
	}

	/**
	 * イベント出力結果をチェックする。<br>
	 * 
	 * @param jobInfo ジョブ情報
	 * @param priority 重要度
	 * @param fromDate 出力日時（開始）
	 * @param toDate 出力日時（終了）
	 * @return CSVフォーマット文字列
	 */
	protected ArrayList<String> checkEventByPriority(JobInfo jobInfo, int priority, Date fromDate, Date toDate) {
		ArrayList<String> csvFormat = new ArrayList<String>();

		String jobType = JobConstant.typeToString(jobInfo.getType());
		String[] args = {jobType,jobInfo.getName(),jobInfo.getId()};
		String msg = "";
		if(priority == PriorityConstant.TYPE_INFO){
			msg = Messages.getMsg("message.job.2", args);
		}
		else if(priority == PriorityConstant.TYPE_WARNING){
			msg = Messages.getMsg("message.job.3", args);
		}
		else if(priority == PriorityConstant.TYPE_CRITICAL){
			msg = Messages.getMsg("message.job.4", args);
		}

		ReportEventInfo startEvent = null;
		ReportEventInfo endEvent = findEvent(msg, fromDate, toDate);
		if(endEvent instanceof ReportEventInfo && 
				endEvent.getMessage() instanceof String){
			String startMsg = Messages.getMsg("message.job.1", args) + endEvent.getMessage().substring(msg.length());
			startEvent = findEvent(startMsg, fromDate, toDate);
		}

		if(startEvent instanceof ReportEventInfo)
			csvFormat.add(DateFormat.getDateTimeInstance().format(startEvent.getGenerationDate()));
		else
			csvFormat.add("");

		if(endEvent instanceof ReportEventInfo)
			csvFormat.add(DateFormat.getDateTimeInstance().format(endEvent.getGenerationDate()));
		else
			csvFormat.add("");

		return csvFormat;
	}

	/**
	 * イベントを検索する。<br>
	 * 
	 * @param msg 検索対象メッセージ
	 * @param fromDate 出力日時（開始）
	 * @param toDate 出力日時（終了）
	 * @return イベント
	 */
	protected ReportEventInfo findEvent(String msg, Date fromDate, Date toDate) {
		ArrayList<ReportEventInfo> eventList = 
			EjbConnectionManager.getConnectionManager().getEvent(
					null, fromDate, toDate);

		ReportEventInfo newEvent = null;
		for (ReportEventInfo event : eventList) {
			if(event.getMessage() instanceof String && 
					event.getMessage().indexOf(msg) != -1){
				if(newEvent instanceof ReportEventInfo){
					if(newEvent.getGenerationDate().before(event.getGenerationDate()))
						newEvent = event;
				}
				else{
					newEvent = event;
				}
			}
		}

		return newEvent;
	}

	/**
	 * ジョブツリーを取得する。<br>
	 * 
	 * @return ジョブツリー
	 */
	protected JobTreeItem getJobTree() {

		JobController job = EjbConnectionManager.getConnectionManager().getJobController();

		JobTreeItem jobTree = null;
		try {
			jobTree = job.getJobTree(true, Locale.getDefault());
		} catch (Exception e) {
			log.error(Messages.getMsg("TestTool.ConnectManagerFailed"), e);
			System.exit(14);
		}
		return jobTree;
	}
}