/*

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

import java.sql.Time;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;

import javax.ejb.DuplicateKeyException;
import javax.ejb.FinderException;

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.ReadCsvFile;
import jp.co.intellilink.hinemos.importtool.util.SelectArrayList;

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

import com.clustercontrol.bean.DayOfWeekConstant;
import com.clustercontrol.bean.Property;
import com.clustercontrol.bean.PropertyConstant;
import com.clustercontrol.bean.YesNoConstant;
import com.clustercontrol.calendar.bean.AddListTableDefine;
import com.clustercontrol.calendar.bean.CalendarListTableDefine;
import com.clustercontrol.calendar.bean.WeekdayListTableDefine;
import com.clustercontrol.calendar.ejb.session.CalendarController;
import com.clustercontrol.calendar.factory.AddProperty;
import com.clustercontrol.calendar.factory.CalendarProperty;
import com.clustercontrol.calendar.factory.WeekdayProperty;
import com.clustercontrol.util.PropertyUtil;

/**
 * カレンダ情報をインポートするクラス<br>
 * 
 * @version 1.1.0
 * @since 1.1.0
 */
public class ImportCalendar {

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

	private SimpleDateFormat formatTime1 = new SimpleDateFormat("HH:mm:ss");
	private SimpleDateFormat formatTime2 = new SimpleDateFormat("HH:mm");

	private ArrayList<ArrayList<String>> calendarInfos = null;
	private ArrayList<ArrayList<String>> calendarRuleInfos = null;
	private ArrayList<ArrayList<String>> calendarExceptionInfos = null;

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

	/**
	 * カレンダ情報をインポートする。<br>
	 */
	public void importCalendar() {
		log.info(Messages.getMsg("ImportTool.Calendar.Start"));

		//カレンダ情報のCSVファイルを読み込む
		calendarInfos = ReadCsvFile.readCsvFile(Config.getConfig("Input.Dir.Conf") + "/CALENDAR.csv");

		//カレンダ実行規則情報のCSVファイルを読み込む
		calendarRuleInfos = ReadCsvFile.readCsvFile(Config.getConfig("Input.Dir.Conf") + "/CALENDAR_RULE.csv");

		//カレンダ実行例外情報のCSVファイルを読み込む
		calendarExceptionInfos = ReadCsvFile.readCsvFile(Config.getConfig("Input.Dir.Conf") + "/CALENDAR_EXCEPTION.csv");

		//カレンダ一覧取得
		calendarList = getCalendarList();

		for(ArrayList<String> info : calendarInfos){
			String calendarId = info.get(0);
			//カレンダ登録
			Property calendarProperty = createCalenderInfo(info);
			registerCalendarInfo(calendarProperty);

			//カレンダ実行規則削除
			deleteRuleInfo(calendarId);
			//カレンダ実行規則登録
			ArrayList<ArrayList<String>> ruleInfos = 
				SelectArrayList.select(calendarRuleInfos, 0, calendarId);
			for(ArrayList<String> ruleInfo : ruleInfos){
				Property ruleProperty = createRuleInfo(ruleInfo);
				registerRuleInfo(calendarId, ruleProperty);				
			}

			//カレンダ実行例外削除
			deleteExceptionInfo(calendarId);
			//カレンダ実行例外登録
			ArrayList<ArrayList<String>> exceptionInfos = 
				SelectArrayList.select(calendarExceptionInfos, 0, calendarId);
			for(ArrayList<String> exceptionInfo : exceptionInfos){
				Property exception = createExceptionInfo(exceptionInfo);
				registerExceptionInfo(calendarId, exception);
			}
		}

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

	/**
	 * カレンダ情報を作成する。<br>
	 * 
	 * @param info カレンダ情報配列
	 * @return カレンダ情報オブジェクト
	 */
	public Property createCalenderInfo(ArrayList<String> info) {
		Property property = getCalendarProperty();

		@SuppressWarnings("unchecked")
		ArrayList propertyList = null;

		//カレンダID
		propertyList = PropertyUtil.getProperty(property, CalendarProperty.ID);
		((Property)propertyList.get(0)).setValue(info.get(0));
		//カレンダ名
		propertyList = PropertyUtil.getProperty(property, CalendarProperty.NAME);
		((Property)propertyList.get(0)).setValue(info.get(1));
		//有効期間(開始)
		propertyList = PropertyUtil.getProperty(property, CalendarProperty.VALID_TIME_FROM);
		try {
			((Property)propertyList.get(0)).setValue(DateFormat.getDateTimeInstance().parse(info.get(2)));
		} catch (ParseException e) {
		}
		//有効期間(終了)
		propertyList = PropertyUtil.getProperty(property, CalendarProperty.VALID_TIME_TO);
		try {
			((Property)propertyList.get(0)).setValue(DateFormat.getDateTimeInstance().parse(info.get(3)));
		} catch (ParseException e) {
		}
		//説明
		propertyList = PropertyUtil.getProperty(property, CalendarProperty.DESCRIPTION);
		if(info.size() >= 5)
			((Property)propertyList.get(0)).setValue(info.get(4));

		return property;
	}

	/**
	 * カレンダ実行規則情報を作成する。<br>
	 * 
	 * @param info カレンダ実行規則情報配列
	 * @return カレンダ実行規則情報オブジェクト
	 */
	public Property createRuleInfo(ArrayList<String> info) {
		Property property = getRuleProperty();

		@SuppressWarnings("unchecked")
		ArrayList propertyList = null;

		//曜日
		propertyList = PropertyUtil.getProperty(property, WeekdayProperty.WEEKDAY);
		((Property)propertyList.get(0)).setValue(info.get(1));
		//時刻(開始)
		propertyList = PropertyUtil.getProperty(property, WeekdayProperty.TIME_FROM);
		try {
			((Property)propertyList.get(0)).setValue(formatTime1.parse(info.get(2)));
		} catch (ParseException e) {
			try {
				((Property)propertyList.get(0)).setValue(formatTime2.parse(info.get(2)));
			} catch (ParseException e1) {
			}
		}
		//時刻(終了)
		propertyList = PropertyUtil.getProperty(property, WeekdayProperty.TIME_TO);
		try {
			((Property)propertyList.get(0)).setValue(formatTime1.parse(info.get(3)));
		} catch (ParseException e) {
			try {
				((Property)propertyList.get(0)).setValue(formatTime2.parse(info.get(3)));
			} catch (ParseException e1) {
			}
		}
		//説明
		propertyList = PropertyUtil.getProperty(property, WeekdayProperty.DESCRIPTION);
		if(info.size() >= 5)
			((Property)propertyList.get(0)).setValue(info.get(4));

		return property;
	}

	/**
	 * カレンダ実行例外情報を作成する。<br>
	 * 
	 * @param info カレンダ実行例外配列
	 * @return カレンダ実行例外オブジェクト
	 */
	public Property createExceptionInfo(ArrayList<String> info) {
		Property property = getExceptionProperty();

		@SuppressWarnings("unchecked")
		ArrayList propertyList = null;

		//実行
		propertyList = PropertyUtil.getProperty(property, AddProperty.EXECUTE);
		Boolean exec = YesNoConstant.typeToBoolean(YesNoConstant.stringToType(info.get(1)));
		((Property)propertyList.get(0)).setValue(exec);
		//日時(開始)
		propertyList = PropertyUtil.getProperty(property, AddProperty.TIME_FROM);
		try {
			((Property)propertyList.get(0)).setValue(DateFormat.getDateTimeInstance().parse(info.get(2)));
		} catch (ParseException e) {
		}
		//日時(終了)
		propertyList = PropertyUtil.getProperty(property, AddProperty.TIME_TO);
		try {
			((Property)propertyList.get(0)).setValue(DateFormat.getDateTimeInstance().parse(info.get(3)));
		} catch (ParseException e) {
		}
		//説明
		propertyList = PropertyUtil.getProperty(property, AddProperty.DESCRIPTION);
		if(info.size() >= 5)
			((Property)propertyList.get(0)).setValue(info.get(4));

		return property;
	}

	/**
	 * カレンダ一覧に指定したカレンダIDが存在するかチェックする。<br>
	 * 
	 * @param calendarId カレンダID
	 * @return チェック結果
	 */
	@SuppressWarnings("unchecked")
	protected ArrayList checkCalendarList(String calendarId) {

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

				String id = (String)line.get(CalendarListTableDefine.CALENDAR_ID);
				if(id.compareTo(calendarId) == 0)
					return line;
			}
		}

		return null;
	}

	/**
	 * カレンダ実行例外情報を登録する。<br>
	 * 
	 * @param calendarId カレンダID
	 * @param property カレンダ情報実行例外
	 */
	protected void registerExceptionInfo(String calendarId, Property property) {
		CalendarController cal = EjbConnectionManager.getConnectionManager().getCalendarController();

		@SuppressWarnings("unchecked")
		ArrayList propertyList = null;

		propertyList = PropertyUtil.getProperty(property, AddProperty.TIME_FROM);
		String from = DateFormat.getDateTimeInstance().format((Date)((Property)propertyList.get(0)).getValue());
		propertyList = PropertyUtil.getProperty(property, AddProperty.TIME_TO);
		String to = DateFormat.getDateTimeInstance().format((Date)((Property)propertyList.get(0)).getValue());

		try {
			Object[] args = {calendarId, from, to};
			log.info(Messages.getMsg("ImportTool.CalendarID.Exception", args) + 
					" (" + Messages.getMsg("add") + ")");

			cal.addAddInfo(calendarId, property);
		} catch (Exception e) {
			log.error(Messages.getMsg("ImportTool.ConnectManagerFailed"), e);
			System.exit(14);
		}
	}

	/**
	 * カレンダ実行規則情報を登録する。<br>
	 * 
	 * @param calendarId カレンダID
	 * @param property カレンダ情報実行規則
	 */
	protected void registerRuleInfo(String calendarId, Property property) {
		CalendarController cal = EjbConnectionManager.getConnectionManager().getCalendarController();

		@SuppressWarnings("unchecked")
		ArrayList propertyList = null;

		propertyList = PropertyUtil.getProperty(property, WeekdayProperty.WEEKDAY);
		String weekday = (String)((Property)propertyList.get(0)).getValue();
		propertyList = PropertyUtil.getProperty(property, WeekdayProperty.TIME_FROM);
		String from = formatTime1.format((Date)((Property)propertyList.get(0)).getValue());
		propertyList = PropertyUtil.getProperty(property, WeekdayProperty.TIME_TO);
		String to = formatTime1.format((Date)((Property)propertyList.get(0)).getValue());

		try {
			Object[] args = {calendarId, weekday, from, to};
			log.info(Messages.getMsg("ImportTool.CalendarID.Rule", args) + 
					" (" + Messages.getMsg("add") + ")");

			cal.addWeekday(calendarId, property);
		} catch (Exception e) {
			log.error(Messages.getMsg("ImportTool.ConnectManagerFailed"), e);
			System.exit(14);
		}
	}

	/**
	 * カレンダ情報を登録する。<br>
	 * 
	 * @param property カレンダ情報
	 */
	protected void registerCalendarInfo(Property property) {
		CalendarController cal = EjbConnectionManager.getConnectionManager().getCalendarController();

		@SuppressWarnings("unchecked")
		ArrayList propertyList = null;

		propertyList = PropertyUtil.getProperty(property, CalendarProperty.ID);
		String calendarId = (String)((Property)propertyList.get(0)).getValue();

		try {
			@SuppressWarnings("unchecked")
			ArrayList line = checkCalendarList(calendarId);
			if(line instanceof ArrayList){
				Date createTime = (Date)line.get(CalendarListTableDefine.CREATE_TIME);
				String createUser = (String)line.get(CalendarListTableDefine.CREATOR_NAME);
				propertyList = PropertyUtil.getProperty(property, CalendarProperty.CREATE_TIME);
				((Property)propertyList.get(0)).setValue(createTime);
				propertyList = PropertyUtil.getProperty(property, CalendarProperty.CREATOR_NAME);
				((Property)propertyList.get(0)).setValue(createUser);

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

				cal.modifyCalendar(property);
			}
			else{
				Object[] args = {calendarId};
				log.info(Messages.getMsg("ImportTool.CalendarID", args) + 
						" (" + Messages.getMsg("add") + ")");

				cal.addCalendar(property);
			}
		} catch (DuplicateKeyException e) {
			String args[] = {calendarId};
			log.error(Messages.getMsg("ImportTool.Common.1", args));
			System.exit(20);
		} catch (Exception e) {
			log.error(Messages.getMsg("ImportTool.ConnectManagerFailed"), e);
			System.exit(14);
		}
	}

	/**
	 * カレンダ実行例外を削除する。<br>
	 * 
	 * @param calendarId カレンダID
	 */
	@SuppressWarnings("unchecked")
	protected void deleteExceptionInfo(String calendarId) {
		CalendarController cal = EjbConnectionManager.getConnectionManager().getCalendarController();

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

				Date from = (Date)line.get(AddListTableDefine.TIME_FROM);
				Date to = (Date)line.get(AddListTableDefine.TIME_TO);

				Object[] args = {calendarId, DateFormat.getDateTimeInstance().format(from), DateFormat.getDateTimeInstance().format(to)};
				log.info(Messages.getMsg("ImportTool.CalendarID.Exception", args) + 
						" (" + Messages.getMsg("delete") + ")");

				try {
					cal.deleteAddInfo(calendarId, from, to);
				} catch (FinderException e) {
				} catch (Exception e) {
					log.error(Messages.getMsg("ImportTool.ConnectManagerFailed"), e);
					System.exit(14);
				}
			}
		}
	}

	/**
	 * カレンダ実行規則を削除する。<br>
	 * 
	 * @param calendarId カレンダID
	 */
	@SuppressWarnings("unchecked")
	protected void deleteRuleInfo(String calendarId) {
		CalendarController cal = EjbConnectionManager.getConnectionManager().getCalendarController();

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

				Integer weekday = (Integer)line.get(WeekdayListTableDefine.WEEKDAY);
				Time from = (Time)line.get(WeekdayListTableDefine.TIME_FROM);
				Time to = (Time)line.get(WeekdayListTableDefine.TIME_TO);

				Object[] args = {calendarId, DayOfWeekConstant.typeToString(weekday), formatTime1.format(from), formatTime1.format(to)};
				log.info(Messages.getMsg("ImportTool.CalendarID.Rule", args) + 
						" (" + Messages.getMsg("delete") + ")");

				try {
					cal.deleteWeekday(calendarId, weekday, from, to);
				} catch (FinderException e) {
				} catch (Exception e) {
					log.error(Messages.getMsg("ImportTool.ConnectManagerFailed"), e);
					System.exit(14);
				}
			}
		}
	}

	/**
	 * カレンダ実行例外プロパティを取得する。<br>
	 * 
	 * @return カレンダ実行例外プロパティ
	 */
	protected Property getExceptionProperty() {

		CalendarController cal = EjbConnectionManager.getConnectionManager().getCalendarController();

		Property property = null;
		try {
			property = cal.getAddInfoProperty("", null, null, PropertyConstant.MODE_ADD, Locale.getDefault());
		} catch (Exception e) {
			log.error(Messages.getMsg("ImportTool.ConnectManagerFailed"), e);
			System.exit(14);
		}
		return property;
	}

	/**
	 * カレンダ実行規則プロパティを取得する。<br>
	 * 
	 * @return カレンダ実行規則プロパティ
	 */
	protected Property getRuleProperty() {

		CalendarController cal = EjbConnectionManager.getConnectionManager().getCalendarController();

		Property property = null;
		try {
			property = cal.getWeekdayProperty("", null, null, null, PropertyConstant.MODE_ADD, Locale.getDefault());
		} catch (Exception e) {
			log.error(Messages.getMsg("ImportTool.ConnectManagerFailed"), e);
			System.exit(14);
		}
		return property;
	}

	/**
	 * カレンダプロパティを取得する。<br>
	 * 
	 * @return カレンダプロパティ
	 */
	protected Property getCalendarProperty() {

		CalendarController cal = EjbConnectionManager.getConnectionManager().getCalendarController();

		Property property = null;
		try {
			property = cal.getCalendarProperty("", PropertyConstant.MODE_ADD, Locale.getDefault());
		} catch (Exception e) {
			log.error(Messages.getMsg("ImportTool.ConnectManagerFailed"), e);
			System.exit(14);
		}
		return property;
	}

	/**
	 * カレンダ実行例外一覧を取得する。<br>
	 * 
	 * @return カレンダ実行例外一覧
	 */
	@SuppressWarnings("unchecked")
	protected ArrayList getExceptionList(String calendarId) {

		CalendarController cal = EjbConnectionManager.getConnectionManager().getCalendarController();

		ArrayList list = null;
		try {
			list = cal.getAddList(calendarId);
		} catch (Exception e) {
			log.error(Messages.getMsg("ImportTool.ConnectManagerFailed"), e);
			System.exit(14);
		}
		return list;
	}

	/**
	 * カレンダ実行規則一覧を取得する。<br>
	 * 
	 * @return カレンダ実行規則一覧
	 */
	@SuppressWarnings("unchecked")
	protected ArrayList getRuleList(String calendarId) {

		CalendarController cal = EjbConnectionManager.getConnectionManager().getCalendarController();

		ArrayList list = null;
		try {
			list = cal.getWeekdayList(calendarId);
		} catch (Exception e) {
			log.error(Messages.getMsg("ImportTool.ConnectManagerFailed"), e);
			System.exit(14);
		}
		return list;
	}

	/**
	 * カレンダ一覧を取得する。<br>
	 * 
	 * @return カレンダ一覧
	 */
	@SuppressWarnings("unchecked")
	protected ArrayList getCalendarList() {

		CalendarController cal = EjbConnectionManager.getConnectionManager().getCalendarController();

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