/*
 * MosP - Mind Open Source Project         http://www.mosp.jp/
 * Copyright (C) 1987-2008 MIND Co., Ltd.  http://www.e-mind.co.jp/
 * 
 * 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; either version 2
 * of the License, or (at your option) any later version.
 * 
 * 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.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package jp.mosp.kintai.action;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import jp.mosp.common.CommonConst;
import jp.mosp.common.common.MospConst;
import jp.mosp.common.common.MospException;
import jp.mosp.common.common.MospUtility;

import jp.mosp.kintai.dao.CmRotationDao;
import jp.mosp.kintai.dto.CmRotationDto;
import jp.mosp.kintai.dto.MScheduleDto;
import jp.mosp.kintai.dto.MSyukkinboDto;
import jp.mosp.kintai.vo.ScheduleInputCardVo;

public class ScheduleInputCardAction extends AttendanceTotalAction {

	// コマンド
	private static final String CMD_INPUT_CARD_SHOW	= "K1220";
	private static final String CMD_INPUT_CARD_REGIST	= "K1221";

	/**
	 * コンストラクタ
	 */
	public ScheduleInputCardAction() {
		super();
	}

	/**
	 * アクション
	 */
	public void action() throws Exception {
		// VOの取得及び設定
		ScheduleInputCardVo vo = new ScheduleInputCardVo();
		vo.initVo(cfg, msg, cmd, aspUser, user);
		// VO及びフォワード先の準備
		setVo(vo);
		setUrl(vo.getRetUrl());
		// DBコネクション取得		
		getConnection();
		// ユーザー情報取得
		getInfo(user.getUserId());
		// 対象年月取得
		Date targetMonth = util.getSystemDate();
		// プルダウンのセット
		setPulldownList(vo, targetMonth);
		/*						
		 *  	2008/11/14	m.yoshida	選択情報表示
		 */
		// 対象社員設定
		vo.setSelectKCode(mKihon.getKCode());
		// 人事基本情報の取得
		setSelectBasicInfo(vo);
		// コマンド毎の処理
		if (cmd.equals(CMD_INPUT_CARD_SHOW)) {
			// 表示
			// 対象年月日設定
			vo.setPltYear(String.valueOf(MospUtility.getYear(targetMonth)));
			vo.setPltMonth(String.valueOf(MospUtility.getMonth(targetMonth)));
			vo.setPltScheduleDay(String.valueOf(MospUtility.getDay(targetMonth)));
			// 対象日数設定
			vo.setPltRotationDays("1");
		} else if (cmd.equals(CMD_INPUT_CARD_REGIST)) {
			vo.setParams(request);
			// 登録（件数取得）
			int number = regist(vo);
			// コミット
			commit();
			// メッセージ設定
			request.setAttribute(MospConst.ATT_MESSAGE, 
					MospUtility.getMessage(msg, CommonConst.MSG_NUMBER_OF_UPDATES, String.valueOf(number))
			);
		} else {
			throw new MospException(MospConst.EX_CMD_INVALID);
		}
	}

	/**
	 * プルダウンのセット
	 * @param vo
	 * @param targetMonth
	 * @throws Exception
	 */
	private void setPulldownList(ScheduleInputCardVo vo,Date targetMonth) throws Exception {
		// 開始年月日のプルダウン
		vo.aryPltScheduleYear	= util.getYearArray(MospUtility.getYear (targetMonth), 0, 1);
		vo.aryPltScheduleMonth	= util.getMonthArray();
		vo.aryPltScheduleDay	= util.getDayArray();
		// 勤務パターンプルダウン
		CmRotationDao cmRotationDao = new CmRotationDao();
		cmRotationDao.initDao(cfg, cmd, aspUser, user, conn);
		List<CmRotationDto> listRotation = cmRotationDao.findForCondition(mKihon.getKCode());
		vo.aryPltRotation = new String[listRotation.size()][2];
		for (int i = 0; i < vo.aryPltRotation.length; i++) {
			vo.aryPltRotation[i][0] = listRotation.get(i).getRtCode();
			vo.aryPltRotation[i][1] = listRotation.get(i).getRtName();
		}
		// 日数プルダウンの配列
		vo.aryPltDays = util.getDayArray();
		/*						
		 *  	2008/11/14	m.yoshida	予定登録機能追加対応
		 */
		// 勤務形態
		vo.aryPltWorkType = getWorkTypeArrayNotDeleted();
		// 対象が無かった場合のメッセージ設定
		if (vo.aryPltWorkType.length == 0) {
			vo.setMessage(MospUtility.getMessage(msg, MospConst.MSG_NO_DATA, ""));
		}
	}

	/**
	 * 登録処理
	 * @param vo
	 * @throws Exception
	 */
	private int regist(ScheduleInputCardVo vo) throws Exception {
		// DBコネクション取得
		if (conn == null) {
			getConnection();
		}
		// パラメータの妥当性確認
		vo.validate();
		/*						
		 *  	2008/11/14	m.yoshida	予定登録機能追加対応
		 */
		// 開始日・終了日
		Date startDate;
		Date endDate;
		// 通常週休登録フラグ
		boolean isWeekHoliday = false;
		// 開始日・終了日設定
		if (vo.getCkbSelectPeriod().equals(CommonConst.NAM_COMMON_FLAG_OFF)) {
			/*						
			 *  	2009/01/20	m.yoshida	締め日対応
			 */
			startDate = getStartDateForList(util.getFirstDateOfMonth(vo.getPltYear(), vo.getPltMonth()));
			endDate = getEndDateForList(util.getFirstDateOfMonth(vo.getPltYear(), vo.getPltMonth()));
			isWeekHoliday = true;
		} else {
			startDate = util.getDate(vo.getPltYear(), vo.getPltMonth(), vo.getPltScheduleDay());
			endDate = util.addDay(startDate, vo.getIntParam(vo.getPltRotationDays()) -1);
		}
		/*						
		 *  	2008/11/14	m.yoshida	予定登録機能追加対応
		 */
		// 勤務パターンの勤務形態と祝祭日フラグを取得
		boolean isPublicHoliday = isPublicHoliday(vo.getCkbSelectWorkType(), vo.getPltRotationCode());
		// 勤怠情報設定
		setHours();
		// 開始日、終了日設定
		super.startDate = MospUtility.getDateString(startDate, CommonConst.FORMAT_DATE);
		super.endDate = MospUtility.getDateString(endDate, CommonConst.FORMAT_DATE);
		// 出勤簿の取得と準備
		getAttendanceList(mKihon.getKCode());
		// 配列に日付と勤務形態コードをセット
		String[][] aryScheduleList = makeScheduleList(
				getAryRotation(vo.getCkbSelectWorkType(), vo.getPltRotationCode(), vo.getPltWorkTypeCode()),
				isPublicHoliday,
				isWeekHoliday
		);
		// 更新・登録件数
		int number = 0;
		// 出勤簿の日付の取得
		Date[] attendanceDate = null ;
		if (attendanceList.size() != 0) {
			attendanceDate = new Date[attendanceList.size()];
			for (int k = 0; k < attendanceList.size(); k++) {
				attendanceDate[k] = MospUtility.getDate(attendanceList.get(k).getHizuke());
			}
		}
		// スケジュール登録
		for (int i = 0; i < aryScheduleList.length; i++) {
			// 勤務形態からデフォルトの値を取得し、予定簿DTOにセットする
			if (aryScheduleList[i][1].equals("")) {
				continue;
			}
			MScheduleDto registScheduleDto = setScheduleInfo(
					mKihon.getKCode(),
					mKihon.getSCode(),
					aryScheduleList[i]
			);
			// スケジュールの日付を取得
			Date scheduleDate = MospUtility.getDate(aryScheduleList[i][0]);
			// 日付から出勤簿を検索する
			if (chkExistObject(attendanceDate)) {
				// 出勤確認
				boolean isAttendance = false;
				for (int m = 0; m < attendanceDate.length; m++) {
					if (attendanceDate[m].compareTo(scheduleDate) == 0) {
						isAttendance = true;
						break;
					}
				}
				if (isAttendance) {
					// 出勤簿に既に登録されている場合は予定簿のみ更新
					registSchedule(registScheduleDto, vo);
					number++;
				} else {
					// 出勤簿と予定表に同じ値を登録
					MSyukkinboDto insertSyukkinboDto = copyScheduleInfo(registScheduleDto);
					// 出勤簿に登録
					insert(insertSyukkinboDto, vo);
					// 予定簿に登録
					registSchedule(registScheduleDto, vo);
					number++;
				}
			} else {
				// 出勤簿リストが無い場合
				// 出勤簿と予定表に同じ値を登録
				MSyukkinboDto insertSyukkinboDto = copyScheduleInfo(registScheduleDto);
				// 出勤簿に登録
				insert(insertSyukkinboDto, vo);
				// 予定簿に登録
				registSchedule(registScheduleDto, vo);
				number++;
			}
		}
		// 処理件数をセット
		return number;
	}

	/**
	 * スケジュール配列
	 * <p>	2008/11/14	m.yoshida	予定登録方法追加対応	</p>
	 * @param startDate			開始年月日
	 * @param endDate			終了年月日
	 * @param aryRotation 		勤務パターン配列
	 * @param isPublicHoliday 	祝祭日フラグ
	 * @param isWeekHoliday		通常週休登録フラグ
	 * @return　arySchedule		予定登録用配列
	 * @throws Exception
	 */
	private String[][] makeScheduleList(
			String[] aryRotation,
			boolean isPublicHoliday,
			boolean isWeekHoliday
	) throws Exception {
		// DBコネクション取得
		if (conn == null) {
			getConnection();
		}
		// データ数取得
		Calendar cal = Calendar.getInstance();
		cal.setTime(util.convStringDateToDate(startDate));
		// 日数の設定
		int count = 0;
		while (util.convStringDateToDate(endDate).compareTo(cal.getTime()) >= 0) {
			cal.add(Calendar.DAY_OF_MONTH, 1);
			count++;
		}
		// 配列の初期化
		String[][] arySchedule = new String[count][2];
		for (int i = 0; i < arySchedule.length; i++) {
			arySchedule[i][0] = "";
			arySchedule[i][1] = "";
		}
		// 日付設定
		cal.setTime(util.convStringDateToDate(startDate));
		int irotate = 0;
		int max = aryRotation.length -1;
		for (int i = 0; i < arySchedule.length; i++) {
			if (irotate > max) {
				irotate = 0;
			}
			// 勤務パターンのローテーション
			while (aryRotation[irotate].equals("")) {
				irotate ++;
				if (irotate > max) {
					irotate = 0;
				}
			}
			// 日付
			arySchedule[i][0] = MospUtility.getDateString(cal.getTime(), CommonConst.FORMAT_DATE);
			// 勤務形態コード
			String workTypeCode = aryRotation[irotate];
			// 祝祭日フラグ
			if (getPublicHolidayName(cal.getTime()).length() != 0 && isPublicHoliday) {
				workTypeCode = "";
			}
			// チェックあり
			if (isWeekHoliday) {
				if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY
						|| cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY
				) {
					workTypeCode = CommonConst.ATTENDANCE_TYPE_WEEK_HOLIDAY;
				}
			}
			arySchedule[i][1] = workTypeCode;
			irotate++;
			cal.add(Calendar.DAY_OF_MONTH, 1);
		}
		return arySchedule;
	}

	/**
	 * 対象輪番配列
	 * @param ckbSelect		対象選択機能
	 * @param pltRotation	対象選択輪番コード
	 * @param pltWorkType	対象選択勤務形態コード
	 * @return
	 * @throws Exception
	 */
	private String[] getAryRotation(String ckbSelect, String pltRotation, String pltWorkType) throws Exception {
		if (ckbSelect.equals(CommonConst.NAM_COMMON_FLAG_ON)) {
			return getRotationArray(pltRotation);
		} else {
			return new String[]{pltWorkType};
		}	
	}

	/**
	 * 祝祭日フラグ
	 * @param ckbSelect		対象選択機能
	 * @param pltRotation	対象選択輪番コード
	 * @return
	 * @throws Exception
	 */
	private boolean isPublicHoliday(String ckbSelect, String pltRotation) throws Exception {
		if (ckbSelect.equals(CommonConst.NAM_COMMON_FLAG_ON)) {
			return getPublicHolidayFlag(pltRotation);
		} else {
			return true;
		}
	}

}
