/*

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.export.history;

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

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.Messages;
import jp.co.intellilink.hinemos.util.StringListComparator;
import jp.co.intellilink.hinemos.util.WriteCsvFile;

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

import com.clustercontrol.bean.EndStatusConstant;
import com.clustercontrol.bean.Property;
import com.clustercontrol.bean.StatusConstant;
import com.clustercontrol.bean.ViewListInfo;
import com.clustercontrol.collectiverun.bean.DetailTableDefine;
import com.clustercontrol.collectiverun.bean.HistoryFilterPropertyConstant;
import com.clustercontrol.collectiverun.bean.HistoryTableDefine;
import com.clustercontrol.collectiverun.ejb.session.CollectiveRunController;
import com.clustercontrol.util.PropertyUtil;

/**
 * 一括制御実行履歴を取得するクラス<br>
 * 
 * @version 1.0.0
 * @since 1.0.0
 */
public class ExportCollectiveRun {

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

	/**
	 * 一括制御履歴をExportする。<br>
	 * 
	 * @param startDate 開始日時
	 */
	public void export(Date startDate) {
		log.info(Messages.getMsg("CollectiveRun.Start", new String[]{Messages.getMsg("ExportTool.Export")}));

		//CSV出力配列を用意
		ArrayList<ArrayList<String>> sessionCsvOutput = new ArrayList<ArrayList<String>>();
		//CSV出力配列を用意
		ArrayList<ArrayList<String>> nodeCsvOutput = new ArrayList<ArrayList<String>>();

		Calendar cal = Calendar.getInstance();
		cal.setTime(startDate);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		Date startTime = cal.getTime();

		cal.add(Calendar.DATE, 1);
		cal.add(Calendar.MILLISECOND, -1);
		Date endTime = cal.getTime();

		//ジョブセッション一覧
		ViewListInfo info = getSessionList(startTime, endTime);

		if(info.getList() instanceof ArrayList){
			Iterator itr = info.getList().iterator();
			while(itr.hasNext()){
				ArrayList line = (ArrayList)itr.next();
				String sessionId = (String)line.get(HistoryTableDefine.SESSION_ID);

				Object[] args = {sessionId};
				log.info(Messages.getMsg("SessionID", args));

				sessionCsvOutput.add(createSessionCsvFormat(line));
				nodeCsvOutput.addAll(createNodeCsvFormat(line));
			}
		}

		//ファシリティIDでソート
		Collections.sort(sessionCsvOutput, new StringListComparator(6));
		//セッションIDでソート
		Collections.sort(sessionCsvOutput, new StringListComparator(1));

		sessionCsvOutput.add(0, createSessionCsvHeader());

		SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
		WriteCsvFile.writeCsvFile(
				Config.getConfig("History.Dir") + "/CRUN_" + format.format(startTime) + ".csv", 
				sessionCsvOutput);

		//ファシリティIDでソート
		Collections.sort(nodeCsvOutput, new StringListComparator(4));
		//セッションIDでソート
		Collections.sort(nodeCsvOutput, new StringListComparator(3));

		nodeCsvOutput.add(0, createNodeCsvHeader());

		WriteCsvFile.writeCsvFile(
				Config.getConfig("History.Dir") + "/CRUN_NODE_" + format.format(startTime) + ".csv", 
				nodeCsvOutput);

		log.info(Messages.getMsg("CollectiveRun.End", new String[]{Messages.getMsg("ExportTool.Export")}));
	}

	/**
	 * 履歴一覧用CSVフォーマットのヘッダ文字列を作成する。<br>
	 * 
	 * @return CSVフォーマット文字列
	 */
	public ArrayList<String> createSessionCsvHeader() {
		ArrayList<String> csvLine = new ArrayList<String>();

		csvLine.add(com.clustercontrol.util.Messages.getString("run.status"));
		csvLine.add(com.clustercontrol.util.Messages.getString("session.id"));
		csvLine.add(com.clustercontrol.util.Messages.getString("start.time"));
		csvLine.add(com.clustercontrol.util.Messages.getString("end.time"));
		csvLine.add(com.clustercontrol.util.Messages.getString("type"));
		csvLine.add(com.clustercontrol.util.Messages.getString("name"));
		csvLine.add(com.clustercontrol.util.Messages.getString("facility.id"));
		csvLine.add(com.clustercontrol.util.Messages.getString("scope"));
		csvLine.add(com.clustercontrol.util.Messages.getString("total"));
		csvLine.add(com.clustercontrol.util.Messages.getString("successful"));
		csvLine.add(com.clustercontrol.util.Messages.getString("warning"));
		csvLine.add(com.clustercontrol.util.Messages.getString("failed"));
		csvLine.add(com.clustercontrol.util.Messages.getString("waiting"));
		csvLine.add(com.clustercontrol.util.Messages.getString("running"));

		return csvLine;
	}

	/**
	 * 詳細一覧用CSVフォーマットのヘッダ文字列を作成する。<br>
	 * 
	 * @return CSVフォーマット文字列
	 */
	public ArrayList<String> createNodeCsvHeader() {
		ArrayList<String> csvLine = new ArrayList<String>();

		csvLine.add(com.clustercontrol.util.Messages.getString("run.status"));
		csvLine.add(com.clustercontrol.util.Messages.getString("end.status"));
		csvLine.add(com.clustercontrol.util.Messages.getString("return.value"));
		csvLine.add(com.clustercontrol.util.Messages.getString("session.id"));
		csvLine.add(com.clustercontrol.util.Messages.getString("facility.id"));
		csvLine.add(com.clustercontrol.util.Messages.getString("facility.name"));
		csvLine.add(com.clustercontrol.util.Messages.getString("start.time"));
		csvLine.add(com.clustercontrol.util.Messages.getString("end.time"));
		csvLine.add(com.clustercontrol.util.Messages.getString("message"));

		return csvLine;
	}

	/**
	 * 履歴一覧用のCSVフォーマット文字列を作成する。<br>
	 * 
	 * @param info 履歴情報
	 * @return CSVフォーマット文字列
	 */
	public ArrayList<String> createSessionCsvFormat(ArrayList info) {
		ArrayList<String> csvFormat = new ArrayList<String>();
		//実行状態
		csvFormat.add(StatusConstant.typeToString(((Number) info.get(HistoryTableDefine.STATUS)).intValue()));
		//セッションID
		csvFormat.add((String) info.get(HistoryTableDefine.SESSION_ID));
		//開始日時
		if(info.get(HistoryTableDefine.START_TIME) instanceof Date)
			csvFormat.add(DateFormat.getDateTimeInstance().format((Date)info.get(HistoryTableDefine.START_TIME)));
		//終了日時
		if(info.get(HistoryTableDefine.END_TIME) instanceof Date)
			csvFormat.add(DateFormat.getDateTimeInstance().format((Date)info.get(HistoryTableDefine.END_TIME)));
		//種別
		csvFormat.add((String) info.get(HistoryTableDefine.TYPE));
		//名前
		csvFormat.add((String) info.get(HistoryTableDefine.NAME));
		//ファシリティID
		csvFormat.add((String) info.get(HistoryTableDefine.FACILITY_ID));
		//スコープ
		csvFormat.add((String) info.get(HistoryTableDefine.SCOPE));
		//合計
		if(info.get(HistoryTableDefine.TOTAL) instanceof Number)
			csvFormat.add(((Number) info.get(HistoryTableDefine.TOTAL)).toString());
		//成功
		if(info.get(HistoryTableDefine.NORMAL) instanceof Number)
			csvFormat.add(((Number) info.get(HistoryTableDefine.NORMAL)).toString());
		//警告
		if(info.get(HistoryTableDefine.WARNING) instanceof Number)
			csvFormat.add(((Number) info.get(HistoryTableDefine.WARNING)).toString());
		//失敗
		if(info.get(HistoryTableDefine.ABNORMAL) instanceof Number)
			csvFormat.add(((Number) info.get(HistoryTableDefine.ABNORMAL)).toString());
		//待機中
		if(info.get(HistoryTableDefine.WAITING) instanceof Number)
			csvFormat.add(((Number) info.get(HistoryTableDefine.WAITING)).toString());
		//実行中
		if(info.get(HistoryTableDefine.RUNNING) instanceof Number)
			csvFormat.add(((Number) info.get(HistoryTableDefine.RUNNING)).toString());
		return csvFormat;
	}

	/**
	 * 詳細一覧用のCSVフォーマット文字列を作成する。<br>
	 * 
	 * @param info 詳細情報
	 * @return CSVフォーマット文字列
	 */
	public ArrayList<ArrayList<String>> createNodeCsvFormat(ArrayList info) {
		ArrayList<ArrayList<String>> csvOutput = new ArrayList<ArrayList<String>>();

		String sessionId = (String)info.get(HistoryTableDefine.SESSION_ID);
		ArrayList list = getNodeList(sessionId);
		if(list instanceof ArrayList){
			Iterator itr = list.iterator();
			while(itr.hasNext()){
				ArrayList line = (ArrayList)itr.next();

				ArrayList<String> csvFormat = new ArrayList<String>();
				//実行状態
				csvFormat.add(StatusConstant.typeToString(((Number) line.get(DetailTableDefine.STATUS)).intValue()));
				//終了状態
				if(line.get(DetailTableDefine.END_STATUS) instanceof Number)
					csvFormat.add(EndStatusConstant.typeToString(((Number) line.get(DetailTableDefine.END_STATUS)).intValue()));
				else
					csvFormat.add("");
				if(line.get(DetailTableDefine.RETURN_VALUE) instanceof Number)
					csvFormat.add(((Number) line.get(DetailTableDefine.RETURN_VALUE)).toString());
				else
					csvFormat.add("");
				//セッションID
				csvFormat.add(sessionId);
				//ファシリティID
				csvFormat.add((String) line.get(DetailTableDefine.FACILITY_ID));
				//ファシリティ名
				csvFormat.add((String) line.get(DetailTableDefine.FACILITY_NAME));
				//開始日時
				if(line.get(DetailTableDefine.START_TIME) instanceof Date)
					csvFormat.add(DateFormat.getDateTimeInstance().format((Date)line.get(DetailTableDefine.START_TIME)));
				//終了日時
				if(line.get(DetailTableDefine.END_TIME) instanceof Date)
					csvFormat.add(DateFormat.getDateTimeInstance().format((Date)line.get(DetailTableDefine.END_TIME)));
				//メッセージ
				if(line.get(DetailTableDefine.MESSAGE) instanceof String)
					csvFormat.add(CheckString.checkReturn((String) line.get(DetailTableDefine.MESSAGE)));
				else
					csvFormat.add("");

				csvOutput.add(csvFormat);
			}
		}

		return csvOutput;
	}

	/**
	 * 履歴一覧を取得する。<br>
	 * 
	 * @param fromDate 開始日時
	 * @param toDate 終了日時
	 * @return 履歴一覧
	 */
	protected ViewListInfo getSessionList(Date fromDate, Date toDate) {

		CollectiveRunController collectiveRun = EjbConnectionManager.getConnectionManager().getCollectiveRunController();

		ViewListInfo info = null;
		try {
			ArrayList properties = null;
			Property filter = collectiveRun.getHistoryFilterProperty(Locale.getDefault());

			//開始・再実行日時（開始）を設定
			if(fromDate instanceof Date){
				properties = PropertyUtil.getProperty(filter, HistoryFilterPropertyConstant.START_FROM_DATE);
				((Property)properties.get(0)).setValue(fromDate);
			}

			//開始・再実行日時（終了）を設定
			if(toDate instanceof Date){
				properties = PropertyUtil.getProperty(filter, HistoryFilterPropertyConstant.START_TO_DATE);
				((Property)properties.get(0)).setValue(toDate);
			}

			int maxlist = Integer.parseInt(Config.getConfig("history.crun.max.list"));

			info = collectiveRun.getHistoryList(filter, Locale.getDefault(), maxlist);
		} catch (Exception e) {
			log.error(Messages.getMsg("ConnectManagerFailed"), e);
			System.exit(14);
		}
		return info;
	}

	/**
	 * 詳細一覧を取得する。<br>
	 * 
	 * @param sessionId セッションID
	 * @return 詳細一覧
	 */
	protected ArrayList getNodeList(String sessionId) {

		CollectiveRunController collectiveRun = EjbConnectionManager.getConnectionManager().getCollectiveRunController();

		ArrayList list = null;
		try {
			list = collectiveRun.getDetailList(sessionId, Locale.getDefault());
		} catch (Exception e) {
			log.error(Messages.getMsg("ConnectManagerFailed"), e);
			System.exit(14);
		}
		return list;
	}
}