/*

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

import java.util.ArrayList;
import java.util.Calendar;
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.JobUtil;
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.DayOfWeekConstant;
import com.clustercontrol.bean.Schedule;
import com.clustercontrol.bean.ScheduleConstant;
import com.clustercontrol.bean.ValidConstant;
import com.clustercontrol.jobmanagement.bean.JobTreeItem;
import com.clustercontrol.jobmanagement.bean.ScheduleInfo;
import com.clustercontrol.jobmanagement.bean.ScheduleTableDefine;
import com.clustercontrol.jobmanagement.ejb.session.JobController;

/**
 * スケジュール情報をImportするクラス<br>
 * 
 * @version 1.0.0
 * @since 1.0.0
 */
public class ImportSchedule {

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

	private ArrayList<ArrayList<String>> scheduleInfo = null;
	@SuppressWarnings("unchecked")
	private ArrayList scheduleList = null;
	private JobTreeItem jobTreeItem = null;

	/**
	 * スケジュール情報をImportする。<br>
	 */
	public void importSchedule() {
		log.info(Messages.getMsg("Job.Schedule.Start", new String[]{Messages.getMsg("ImportTool.Import")}));

		//スケジュール情報のCSVファイルを読み込む
		scheduleInfo = ReadCsvFile.readCsvFile(Config.getConfig("Import.Dir") + "/JOB_SCHEDULE.csv");

		//ジョブツリーを取得
		jobTreeItem = getJobTree();
		
		//スケジュール一覧を取得
		scheduleList = getScheduleList();

		for(ArrayList<String> schedule : scheduleInfo){
			ScheduleInfo info = createScheduleInfo(schedule);
			registerSchedule(info);
		}

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

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

		//スケジュールID
		String id = CheckString.checkLength(scheduleInfo.get(0), DataRangeConstant.VARCHAR_80);
		if(!id.equals(scheduleInfo.get(0))){
			String[] args = { com.clustercontrol.util.Messages.getString("schedule.id"), "80" };
			log.error(Messages.getMsg("ImportTool.Common.2", args));
			System.exit(20);
		}
		info.setId(id);
		//スケジュール名
		String name = CheckString.checkLength(scheduleInfo.get(1), DataRangeConstant.VARCHAR_120);
		if(!name.equals(scheduleInfo.get(1))){
			String[] args = { com.clustercontrol.util.Messages.getString("schedule.name"), "120" };
			log.warn(Messages.getMsg("ImportTool.Common.2", args));
		}
		info.setName(name);
		//ジョブID
		info.setJobId(scheduleInfo.get(2));
		if(!JobUtil.findJobId(info.getJobId(), jobTreeItem)){
			String args[] = {info.getId(), info.getJobId()};
			log.error(Messages.getMsg("ImportTool.Job.5", args));
			System.exit(20);
		}
		//ジョブ名
		info.setJobName(scheduleInfo.get(3));
		//カレンダID
		info.setCalendarId(scheduleInfo.get(4));

		Schedule schedule = new Schedule();
		Integer month = null;
		Integer day = null;
		Integer hours = null;
		Integer minutes = null;
		Integer week = null;
		if(scheduleInfo.get(5).compareTo(com.clustercontrol.util.Messages.getString("time")) == 0){
			//月を取得
			if (scheduleInfo.get(6).length() > 0) {
				month = Integer.parseInt(scheduleInfo.get(6));
			}
			//日を取得
			if (scheduleInfo.get(7).length() > 0) {
				day = Integer.parseInt(scheduleInfo.get(7));
			}
			//時を取得
			if (scheduleInfo.get(8).length() > 0) {
				hours = Integer.parseInt(scheduleInfo.get(8));
			}
			//分を取得
			if (scheduleInfo.get(9).length() > 0) {
				minutes = Integer.parseInt(scheduleInfo.get(9));
			}

			//スケジュール種別ごとにチェック
			if (scheduleInfo.get(6).length() == 0
					&& scheduleInfo.get(7).length() == 0
					&& scheduleInfo.get(8).length() == 0) {
				//スケジュール種別に毎時を設定
				schedule.setType(ScheduleConstant.TYPE_EVERY_HOUR);
			} else if (scheduleInfo.get(6).length() == 0
					&& scheduleInfo.get(7).length() == 0) {
				//スケジュール種別に毎日を設定
				schedule.setType(ScheduleConstant.TYPE_EVERY_DAY);
			} else if (scheduleInfo.get(6).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 (scheduleInfo.get(10).length() > 0) {
				week = new Integer(DayOfWeekConstant
						.stringToType(scheduleInfo.get(10)));
			}
			//時を取得
			if (scheduleInfo.get(11).length() > 0) {
				hours = Integer.parseInt(scheduleInfo.get(11));
			}
			//分を取得
			if (scheduleInfo.get(12).length() > 0) {
				minutes = Integer.parseInt(scheduleInfo.get(12));
			}

			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());
		info.setSchedule(schedule);

		//有効/無効取得
		info.setValid(ValidConstant.stringToType(scheduleInfo.get(13)));

		return info;
	}

	/**
	 * スケジュールを登録する。<br>
	 * 
	 * @param info スケジュール情報
	 */
	protected void registerSchedule(ScheduleInfo info) {

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

		try {
			@SuppressWarnings("unchecked")
			ArrayList schedule = checkScheduleList(info.getId());
			if(schedule instanceof ArrayList){

				Date createTime = (Date)schedule.get(ScheduleTableDefine.CREATE_TIME);
				String createUser = (String)schedule.get(ScheduleTableDefine.CREATE_USER);
				info.setCreateTime(createTime);
				info.setCreateUser(createUser);

				Object[] args = {info.getId()};
				log.info(Messages.getMsg("ScheduleID", args) + 
						" (" + Messages.getMsg("modify") + ")");

				job.modifySchedule(info);
			}
			else{
				Object[] args = {info.getId()};
				log.info(Messages.getMsg("ScheduleID", args) + 
						" (" + Messages.getMsg("add") + ")");

				job.addSchedule(info);
			}
		} catch (Exception e) {
			log.error(Messages.getMsg("ConnectManagerFailed"), e);
			System.exit(14);
		}
	}

	/**
	 * スケジュール一覧に指定したスケジュールIDが存在するかチェックする。<br>
	 * 
	 * @param scheduleId スケジュールID
	 * @return チェック結果
	 */
	@SuppressWarnings("unchecked")
	protected ArrayList checkScheduleList(String scheduleId) {

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

				String id = (String)line.get(ScheduleTableDefine.SCHE_ID);
				if(id.compareTo(scheduleId) == 0)
					return line;
			}
		}

		return null;
	}

	/**
	 * スケジュール一覧を取得する。<br>
	 * 
	 * @return スケジュール一覧
	 */
	@SuppressWarnings("unchecked")
	protected ArrayList getScheduleList() {

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

		ArrayList list = null;
		try {
			list = job.getScheduleList();
		} catch (Exception e) {
			log.error(Messages.getMsg("ConnectManagerFailed"), e);
			System.exit(14);
		}
		return list;
	}
	
	/**
	 * ジョブツリーを取得する。<br>
	 * 
	 * @return ジョブツリー
	 */
	protected JobTreeItem getJobTree() {

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

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