/*

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.maintenance;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.ejb.DuplicateKeyException;

import jp.co.intellilink.hinemos.importtool.util.Config;
import jp.co.intellilink.hinemos.importtool.util.EjbConnectionManager;
import jp.co.intellilink.hinemos.importtool.util.Messages;
import jp.co.intellilink.hinemos.importtool.util.NotifyUtil;
import jp.co.intellilink.hinemos.importtool.util.ReadCsvFile;

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

import com.clustercontrol.bean.DayOfWeekConstant;
import com.clustercontrol.bean.NotifyTypeConstant;
import com.clustercontrol.bean.Schedule;
import com.clustercontrol.bean.ScheduleConstant;
import com.clustercontrol.bean.ValidConstant;
import com.clustercontrol.maintenance.bean.MaintenanceInfoDataImp;
import com.clustercontrol.maintenance.bean.MaintenanceKeepMstConstant;
import com.clustercontrol.maintenance.bean.MaintenanceTypeMstConstant;
import com.clustercontrol.maintenance.bean.ScheduleInfo;
import com.clustercontrol.maintenance.bean.ScheduleTableDefine;
import com.clustercontrol.maintenance.ejb.session.MaintenanceController;
import com.clustercontrol.notify.bean.NotifyRelationInfo;

/**
 * メンテナンス機能情報をインポートするクラス<br>
 * 
 * @version 1.1.0
 * @since 1.1.0
 */
public class ImportMaintenance {

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

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

	private ArrayList<ArrayList<String>> monitorInfos = null;

	/**
	 * メンテナンス機能情報をインポートする。<br>
	 */
	public void importMaintenance() {
		log.info(Messages.getMsg("ImportTool.Maintenance.Start"));

		//メンテナンス情報のCSVファイルを読み込む
		monitorInfos = ReadCsvFile.readCsvFile(Config.getConfig("Input.Dir.Conf") + "/MAINTENANCE.csv");

		//メンテナンスIDリスト取得
		maintenanceList = getMaintenanceList();

		for(ArrayList<String> info : monitorInfos){
			MaintenanceInfoDataImp maintenanceInfo = createMaintenanceInfo(info);
			ScheduleInfo scheduleInfo = createScheduleInfo(info);
			registerMaintenanceInfo(maintenanceInfo, scheduleInfo);
		}

		log.info(Messages.getMsg("ImportTool.Maintenance.End"));
	}

	/**
	 * メンテナンス情報を作成する。<br>
	 * 
	 * @param info メンテナンス情報配列
	 * @return メンテナンス情報
	 */
	public MaintenanceInfoDataImp createMaintenanceInfo(ArrayList<String> info) {
		MaintenanceInfoDataImp maintenanceInfo = new MaintenanceInfoDataImp();

		//メンテナンスID
		maintenanceInfo.setMaintenance_id(info.get(0));
		//説明
		maintenanceInfo.setDescription(info.get(1));
		//メンテナンス種別
		if(info.get(2).equals(com.clustercontrol.util.Messages.getString(MaintenanceTypeMstConstant.DELETE_EVENT_LOG_NAME)))
			maintenanceInfo.setType_id(MaintenanceTypeMstConstant.DELETE_EVENT_LOG);
		else if(info.get(2).equals(com.clustercontrol.util.Messages.getString(MaintenanceTypeMstConstant.DELETE_JOB_HISTORY_NAME)))
			maintenanceInfo.setType_id(MaintenanceTypeMstConstant.DELETE_JOB_HISTORY);
		else if(info.get(2).equals(com.clustercontrol.util.Messages.getString(MaintenanceTypeMstConstant.DELETE_CRUN_HISTORY_NAME)))
			maintenanceInfo.setType_id(MaintenanceTypeMstConstant.DELETE_CRUN_HISTORY);
		//削除対象外の期間
		if(info.get(3).equals(com.clustercontrol.util.Messages.getString(MaintenanceKeepMstConstant.ONE_MONTH_NAME)))
			maintenanceInfo.setKeep_id(MaintenanceKeepMstConstant.ONE_MONTH);
		else if(info.get(3).equals(com.clustercontrol.util.Messages.getString(MaintenanceKeepMstConstant.ONE_WEEK_NAME)))
			maintenanceInfo.setKeep_id(MaintenanceKeepMstConstant.ONE_WEEK);
		else if(info.get(3).equals(com.clustercontrol.util.Messages.getString(MaintenanceKeepMstConstant.ONE_YEAR_NAME)))
			maintenanceInfo.setKeep_id(MaintenanceKeepMstConstant.ONE_YEAR);
		else if(info.get(3).equals(com.clustercontrol.util.Messages.getString(MaintenanceKeepMstConstant.SIX_MONTHS_NAME)))
			maintenanceInfo.setKeep_id(MaintenanceKeepMstConstant.SIX_MONTHS);
		else if(info.get(3).equals(com.clustercontrol.util.Messages.getString(MaintenanceKeepMstConstant.THREE_MONTHS_NAME)))
			maintenanceInfo.setKeep_id(MaintenanceKeepMstConstant.THREE_MONTHS);
		else if(info.get(3).equals(com.clustercontrol.util.Messages.getString(MaintenanceKeepMstConstant.TWO_MONTHS_NAME)))
			maintenanceInfo.setKeep_id(MaintenanceKeepMstConstant.TWO_MONTHS);
		else if(info.get(3).equals(com.clustercontrol.util.Messages.getString(MaintenanceKeepMstConstant.TWO_WEEKS_NAME)))
			maintenanceInfo.setKeep_id(MaintenanceKeepMstConstant.TWO_WEEKS);
		//カレンダID
		maintenanceInfo.setCalendar_id(info.get(4));
		//スケジュール
		Schedule schedule = createSchedule(info.subList(5, 13));
		maintenanceInfo.setSchedule_date(new Timestamp(schedule.getDate().getTime()));
		//通知
		createNotify(info.subList(13, 18), maintenanceInfo);
		//アプリケーション
		maintenanceInfo.setApplication(info.get(18));
		//有効/無効
		maintenanceInfo.setValid_flg(ValidConstant.stringToType(info.get(19)));

		return maintenanceInfo;
	}

	/**
	 * スケジュール情報を作成する。<br>
	 * 
	 * @param info メンテナンス情報配列
	 * @return スケジュール情報
	 */
	public ScheduleInfo createScheduleInfo(ArrayList<String> info) {
		ScheduleInfo scheduleInfo = new ScheduleInfo();

		//メンテナンスID
		scheduleInfo.setId(info.get(0));
		scheduleInfo.setJobId(info.get(0));
		//説明
		scheduleInfo.setName(info.get(1));
		scheduleInfo.setJobName(info.get(1));
		//カレンダID
		scheduleInfo.setCalendarId(info.get(4));
		//スケジュール
		Schedule schedule = createSchedule(info.subList(5, 13));
		scheduleInfo.setSchedule(schedule);
		//有効/無効
		scheduleInfo.setValid(ValidConstant.stringToType(info.get(19)));

		return scheduleInfo;
	}

	/**
	 * メンテナンス通知情報を設定する。<br>
	 * 
	 * @param info メンテナンス情報配列
	 * @param maintenanceInfo メンテナンス情報オブジェクト
	 */
	protected void createNotify(List<String> info, MaintenanceInfoDataImp maintenanceInfo) {
		maintenanceInfo.setNotifyGroupId(NotifyRelationInfo.createNotifyGroupIdMaintenance(maintenanceInfo.getMaintenance_id()));

		ArrayList<NotifyRelationInfo> notifyList = new ArrayList<NotifyRelationInfo>();

		for(int i = 0; i < 5; i++){
			if(info.get(i) instanceof String && info.get(i).length() > 0){
				if(!NotifyUtil.findNotifyId(info.get(i))){
					String args[] = {maintenanceInfo.getMaintenance_id(), info.get(i)};
					log.error(Messages.getMsg("ImportTool.Notify.1", args));
					System.exit(20);
				}

				NotifyRelationInfo relationInfo = new NotifyRelationInfo();
				relationInfo.setNotifyId(info.get(i));
				relationInfo.setNotifyGroupId(maintenanceInfo.getNotifyGroupId());
				relationInfo.setNotifyFlg(0);

				if(i == 0)
					relationInfo.setNotifyType(NotifyTypeConstant.TYPE_STATUS);
				else if(i == 1)
					relationInfo.setNotifyType(NotifyTypeConstant.TYPE_EVENT);
				else if(i == 2)
					relationInfo.setNotifyType(NotifyTypeConstant.TYPE_MAIL);
				else if(i == 3)
					relationInfo.setNotifyType(NotifyTypeConstant.TYPE_JOB);
				else if(i == 4)
					relationInfo.setNotifyType(NotifyTypeConstant.TYPE_LOG_ESCALATE);

				notifyList.add(relationInfo);
			}
		}
		maintenanceInfo.setNotifyId(notifyList);
	}

	/**
	 * スケジュール情報を作成する。<br>
	 * 
	 * @param info メンテナンス情報配列
	 * @return スケジュール情報
	 */
	protected Schedule createSchedule(List<String> info) {
		Schedule schedule = new Schedule();
		Integer month = null;
		Integer day = null;
		Integer hours = null;
		Integer minutes = null;
		Integer week = null;
		if(info.get(0).equals(com.clustercontrol.util.Messages.getString("time"))){
			//月を取得
			if (info.get(1).length() > 0) {
				month = Integer.parseInt(info.get(1));
			}
			//日を取得
			if (info.get(2).length() > 0) {
				day = Integer.parseInt(info.get(2));
			}
			//時を取得
			if (info.get(3).length() > 0) {
				hours = Integer.parseInt(info.get(3));
			}
			//分を取得
			if (info.get(4).length() > 0) {
				minutes = Integer.parseInt(info.get(4));
			}

			//スケジュール種別ごとにチェック
			if (info.get(1).length() == 0
					&& info.get(2).length() == 0
					&& info.get(3).length() == 0) {
				//スケジュール種別に毎時を設定
				schedule.setType(ScheduleConstant.TYPE_EVERY_HOUR);
			} else if (info.get(1).length() == 0
					&& info.get(2).length() == 0) {
				//スケジュール種別に毎日を設定
				schedule.setType(ScheduleConstant.TYPE_EVERY_DAY);
			} else if (info.get(1).length() == 0) {
				//スケジュール種別に毎月を設定
				schedule.setType(ScheduleConstant.TYPE_EVERY_MONTH);
			} else {
				//スケジュール種別に毎年を設定
				schedule.setType(ScheduleConstant.TYPE_EVERY_YEAR);
			}

			if (!(month instanceof Integer)) {
				if (schedule.getType() == ScheduleConstant.TYPE_EVERY_YEAR) {
					log.error(com.clustercontrol.util.Messages.getString("message.job.26"));
					return null;
				}
			}
			if (!(day instanceof Integer)) {
				if (schedule.getType() == ScheduleConstant.TYPE_EVERY_YEAR
						|| schedule.getType() == ScheduleConstant.TYPE_EVERY_MONTH) {
					log.error(com.clustercontrol.util.Messages.getString("message.job.27"));
					return null;
				}
			}
			if (!(hours instanceof Integer)) {
				if (schedule.getType() == ScheduleConstant.TYPE_EVERY_YEAR
						|| schedule.getType() == ScheduleConstant.TYPE_EVERY_MONTH
						|| schedule.getType() == ScheduleConstant.TYPE_EVERY_DAY) {
					log.error(com.clustercontrol.util.Messages.getString("message.job.28"));
					return null;
				}
			}
			if (!(minutes instanceof Integer)) {
				log.error(com.clustercontrol.util.Messages.getString("message.job.29"));
				return null;
			}
		}
		else{
			schedule.setType(ScheduleConstant.TYPE_EVERY_WEEK);

			//曜日を取得
			if (info.get(5).length() > 0) {
				week = new Integer(DayOfWeekConstant
						.stringToType(info.get(5)));
			}
			//時を取得
			if (info.get(6).length() > 0) {
				hours = Integer.parseInt(info.get(6));
			}
			//分を取得
			if (info.get(7).length() > 0) {
				minutes = Integer.parseInt(info.get(7));
			}

			if (!(week instanceof Integer)) {
				log.error(com.clustercontrol.util.Messages.getString("message.job.37"));
				return null;
			}
			if (!(hours instanceof Integer)) {
				log.error(com.clustercontrol.util.Messages.getString("message.job.28"));
				return null;
			}
			if (!(minutes instanceof Integer)) {
				log.error(com.clustercontrol.util.Messages.getString("message.job.29"));
				return null;
			}
		}

		//日時を設定
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.YEAR, 0);
		if (month instanceof Integer) {
			calendar.set(Calendar.MONTH, month.intValue() - 1);
		}
		if (day instanceof Integer) {
			calendar.set(Calendar.DAY_OF_MONTH, day.intValue());
		}
		if (hours instanceof Integer) {
			calendar.set(Calendar.HOUR_OF_DAY, hours.intValue());
		}
		if (week instanceof Integer) {
			calendar.set(Calendar.DAY_OF_WEEK, week.intValue());
			schedule.setDayOfWeek(week.intValue());
		}
		calendar.set(Calendar.MINUTE, minutes.intValue());
		calendar.set(Calendar.SECOND, 0);
		schedule.setDate(calendar.getTime());

		return schedule;
	}

	/**
	 * メンテナンス情報を登録する。<br>
	 * 
	 * @param maintenanceInfo メンテナンス情報
	 * @param scheduleInfo スケジュール情報
	 */
	protected void registerMaintenanceInfo(MaintenanceInfoDataImp maintenanceInfo, 
			ScheduleInfo scheduleInfo) {

		MaintenanceController maintenance = EjbConnectionManager.getConnectionManager().getMaintenanceController();

		try {
			@SuppressWarnings("unchecked")
			ArrayList line = checkMaintenanceList(maintenanceInfo.getMaintenance_id());
			if(line instanceof ArrayList){
				Date createTime = (Date)line.get(ScheduleTableDefine.CREATE_TIME);
				String createUser = (String)line.get(ScheduleTableDefine.CREATE_USER);
				maintenanceInfo.setRegDate(new Timestamp(createTime.getTime()));
				maintenanceInfo.setRegUser(createUser);
				scheduleInfo.setCreateTime(createTime);
				scheduleInfo.setCreateUser(createUser);

				Object[] args = {maintenanceInfo.getMaintenance_id()};
				log.info(Messages.getMsg("ImportTool.MaintenanceID", args) + 
						" (" + Messages.getMsg("modify") + ")");

				maintenance.modifyMaintenance(maintenanceInfo, scheduleInfo);
			}
			else{
				Object[] args = {maintenanceInfo.getMaintenance_id()};
				log.info(Messages.getMsg("ImportTool.MaintenanceID", args) + 
						" (" + Messages.getMsg("add") + ")");

				maintenance.addMaintenance(maintenanceInfo, scheduleInfo);
			}
		} catch (DuplicateKeyException e) {
			String args[] = {maintenanceInfo.getMaintenance_id()};
			log.error(Messages.getMsg("ImportTool.Common.1", args));
			System.exit(20);
		} catch (Exception e) {
			log.error(Messages.getMsg("ImportTool.ConnectManagerFailed"), e);
			System.exit(14);
		}
	}

	/**
	 * メンテナンス一覧に指定したメンテナンスIDが存在するかチェックする。<br>
	 * 
	 * @param maintenanceId メンテナンスID
	 * @return チェック結果
	 */
	@SuppressWarnings("unchecked")
	protected ArrayList checkMaintenanceList(String maintenanceId) {

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

				String id = (String)line.get(0);
				if(id.compareTo(maintenanceId) == 0)
					return line;
			}
		}

		return null;
	}

	/**
	 * メンテナンスリストを取得する。<br>
	 * 
	 * @return メンテナンス一覧
	 */
	@SuppressWarnings("unchecked")
	protected ArrayList getMaintenanceList() {

		MaintenanceController maintenance = EjbConnectionManager.getConnectionManager().getMaintenanceController();

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