/*
 * 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.sql.SQLException;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;

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.dto.MScheduleDto;
import jp.mosp.kintai.dto.MSyukkinboDto;
import jp.mosp.kintai.vo.ScheduleEditCardVo;

public class ScheduleEditCardAction extends AttendanceTotalAction {

	// コマンド
	private static final String CMD_EDIT_CARD_SHOW		= "K1240";
	private static final String CMD_EDIT_CARD_SEARCH		= "K1242";
	private static final String CMD_EDIT_CARD_REGIST		= "K1244";

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

	/**
	 * アクション
	 */
	public void action() throws Exception {
		// VOの取得
		ScheduleEditCardVo vo;
		vo = (ScheduleEditCardVo)getStoredVo(CommonConst.VO_SCHEDULE_EDIT_CARD);
		if (vo == null) {
			vo = new ScheduleEditCardVo();
		}
		vo.initVo(cfg, msg, cmd, aspUser, user);
		vo.clearMessage();
		vo.clearErrField();
		storeVo(CommonConst.VO_SCHEDULE_EDIT_CARD, vo);
		// VO及びフォワード先URLの設定
		setVo(vo);
		setUrl(vo.getRetUrl());
		// DBコネクション取得
		getConnection();
		// ユーザー情報取得
		getInfo(user.getUserId());
		// 表示月
		Date current = util.getSystemDate();
		// プルダウン取得
		vo.aryPltYear  = util.getYearArray(MospUtility.getYear (current), 2, 1);
		vo.aryPltMonth = util.getMonthArray();
		vo.aryPltWorkType = util.addArrayFirstRowSpace(getWorkTypeArrayWithWeekHoliday());
		// 対象社員設定
		vo.setSelectKCode(mKihon.getKCode());
		// メッセージ表示
		setMessage(vo);
		// コマンド毎の処理
		if (cmd.equals(CMD_EDIT_CARD_SHOW)) {
			// 表示
			// 対象年月日設定
			vo.setPltYear(String.valueOf(MospUtility.getYear(current)));
			vo.setPltMonth(String.valueOf(MospUtility.getMonth(current)));
			// 検索
			searchScheduleList(vo);	
		} else if (cmd.equals(CMD_EDIT_CARD_SEARCH)) {
			// 対象年月日設定
			vo.setParams(request);
			// 検索
			searchScheduleList(vo);		
		} else if (cmd.equals(CMD_EDIT_CARD_REGIST)) {
			// パラメータ設定
			vo.setParams(request);
			// 登録（件数取得）
			int number = regist(vo);
			// コミット
			commit();
			// 予定確認へ遷移
			setNextCmd(ScheduleConfirmListAction.CMD_CONFIRM_LIST_SEARCH);
			// メッセージ設定
			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 Voインスタンス
	 * @throws Exception
	 */
	private void searchScheduleList(
			ScheduleEditCardVo vo
	) throws Exception {
		// DBコネクション取得
		if (conn == null) {
			getConnection();
		}
		// 勤怠データ取得
		//getScheduleList(vo.getSelectKCode(), vo.getPltYear(), vo.getPltMonth());
		/*						
		 *  	2009/01/20	m.yoshida	締め日対応
		 */
		//getScheduleList(vo.getSelectKCode(), utility.getYearMonth(vo.getPltYear(), vo.getPltMonth()));
		getScheduleListForView(vo.getSelectKCode(), util.getYearMonth(vo.getPltYear(), vo.getPltMonth()));
		// 日集計データ時間設定
		setScheduleHours();
		// 日集計データ配列作成
		makeScheduleArray();
		// 人事基本情報の設定
		setSelectBasicInfo(vo);
		// VO設定
		vo.setFields(aryAttendance);
	}

	/**
	 * 日集計データ配列作成
	 * @throws Exception
	 */
	private void makeScheduleArray() throws Exception {
		// DBコネクション取得
		if (conn == null) {
			getConnection();
		}
		// データ数取得
		Calendar cal = Calendar.getInstance();
		cal.setTime(MospUtility.getDate(startDate));
		int count = 0;
		while (MospUtility.getDate(endDate).compareTo(cal.getTime()) >= 0) {
			cal.add(Calendar.DAY_OF_MONTH, 1);
			count++;
		}
		// 配列初期化
		aryAttendance = new String[count][40];
		for (int i = 0; i < aryAttendance.length; i++) {
			for (int j = 0; j < aryAttendance[i].length; j++) {
				aryAttendance[i][j] = "";
			}
		}
		// 日付設定
		cal.setTime(MospUtility.getDate(startDate));
		for (int i = 0; i < aryAttendance.length; i++) {
			// 日付
			aryAttendance[i][0] = String.valueOf(MospUtility.getMonth(cal.getTime()))
			+ CommonConst.SEPARATOR_DATE
			+ String.valueOf(cal.get(Calendar.DAY_OF_MONTH));
			// 曜日
			aryAttendance[i][1] = getDayOfWeek(cal.get(Calendar.DAY_OF_WEEK));
			// 備考（祝祭日、半休）
			StringBuffer remark = new StringBuffer();
			String holidayName = getPublicHolidayName(cal.getTime());
			if (holidayName.length() != 0) {
				remark.append(holidayName);
				remark.append(CommonConst.NAM_COMMON_HALF_KANA_SPACE);
			}
			aryAttendance[i][8] = remark.toString();
			cal.add(Calendar.DAY_OF_MONTH, 1);
		}
		// データの設定
		Iterator<MScheduleDto> it = scheduleList.iterator();
		while (it.hasNext()) {
			cal.setTime(MospUtility.getDate(startDate));
			MScheduleDto dto = it.next();
			Date scheduleDate = MospUtility.getDate(dto.getHizuke());
			for (int i = 0; i < aryAttendance.length; i++) {
				if (scheduleDate.compareTo(cal.getTime()) == 0) {
					// 勤務形態
					String kinmu = "";
					if (isAvailableWorkType(dto)) {
						kinmu = workTypeMap.get(dto.getKinmu()).getShiftName();
						// 勤務形態コード
						aryAttendance[i][3] = workTypeMap.get(dto.getKinmu()).getShiftCode();						
						// 出勤時刻
						aryAttendance[i][4] = dto.getSyJikoku();
						// 退勤時刻
						aryAttendance[i][5] = dto.getTaJikoku();
						// 勤務時間
						aryAttendance[i][6] = getHourString(util.convIntegerTimeToDoubleTime(dto.getKinmuJi()));
						// 休憩時間
						aryAttendance[i][7] = getHourString(util.convIntegerTimeToDoubleTime(dto.getKyukeiJi()));
					} else if (isWeekHoliday(dto)) {
						// 週休の場合
						kinmu = CommonConst.ATTENDANCE_TYPE_WEEK_HOLIDAY;
						aryAttendance[i][3] = kinmu;
					} else {
						for (int k = 0; k < aryHolidayReason.length; k++) {
							if (aryHolidayReason[k][0].equals(dto.getKKRiyuu())) {
								kinmu = aryHolidayReason[k][1];
							}
						}
					}
					aryAttendance[i][2] = kinmu;
					break;
				}
				cal.add(Calendar.DAY_OF_MONTH, 1);
			}
		}
	}

	/**
	 * 登録処理
	 * @param vo
	 * @return	number
	 * @throws SQLException 
	 * @throws ClassNotFoundException 
	 */
	private int regist(ScheduleEditCardVo vo) throws Exception {
		// DBコネクション取得
		if (conn == null) {
			getConnection();
		}
		// パラメータの妥当性確認
		vo.validate();
		// カレンダーの呼び出し
		Calendar cal = Calendar.getInstance();
		// 対象年月取得
		Date targetMonth = util.getYearMonth(vo.getPltYear(), vo.getPltMonth());
		// 出勤簿の取得と準備
		/*						
		 *  	2009/01/20	m.yoshida	締め日対応
		 */
		getAttendanceListForView(vo.getSelectKCode(), targetMonth);
		// 出勤簿日集計データ時間設定
		setHours();
		// 配列に日付と勤務形態コードをセット
		String[][] aryNewScheduleList = makeNewScheduleList(vo, targetMonth);
		// 更新・登録件数
		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 < aryNewScheduleList.length; i++) {
			if (aryNewScheduleList[i][1].equals("")) {
				// 勤務形態が空欄なら対象日の予定を削除する
				if (!delete(getScheduleInfo(mKihon.getKCode(), aryNewScheduleList[i][0]))) {
					number++;
				}
				continue;
			}
			// 勤務形態からデフォルトの値を取得し、予定簿DTOにセットする
			MScheduleDto registScheduleDto = setScheduleInfo(
					mKihon.getKCode(),
					mKihon.getSCode(),
					aryNewScheduleList[i]);
			// スケジュールの日付を取得
			cal.setTime(MospUtility.getDate(aryNewScheduleList[i][0]));
			// 日付から出勤簿を検索する
			if (chkExistObject(attendanceDate)) {
				// 出勤確認
				boolean isAttendance = false;
				for (int m = 0; m < attendanceDate.length; m++) {
					if (attendanceDate[m].compareTo(cal.getTime()) == 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;
	}

	/**
	 * スケジュール配列
	 * @param vo 対象VO
	 * @param targetMonth 対象月
	 * @return 新規予定簿用配列
	 * @throws Exception
	 */
	private String[][] makeNewScheduleList(ScheduleEditCardVo vo, Date targetMonth) throws Exception {
		// DBコネクション取得
		if (conn == null) {
			getConnection();
		}
		/*						
		 *  	2009/01/20	m.yoshida	締め日対応
		 */
		//Date startDate 	= getStartDate(targetMonth);
		//Date endDate 	= getEndDate(targetMonth);
		Date startDate 	= getStartDateForList(targetMonth);
		Date endDate 	= getEndDateForList(targetMonth);
		// データ数取得
		Calendar cal = Calendar.getInstance();
		cal.setTime(startDate);
		// 日数の設定
		int count = 0;
		while (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(startDate);
		for (int i = 0; i < arySchedule.length; i++) {
			// 日付
			arySchedule[i][0] = MospUtility.getDateString(cal.getTime(), CommonConst.FORMAT_DATE);
			arySchedule[i][1] = vo.getArySelectWorktype()[i];
			cal.add(Calendar.DAY_OF_MONTH, 1);
		}
		return arySchedule;
	}

	/**
	 * 予定簿の削除処理
	 * @param dto
	 * @throws Exception
	 */
	private boolean delete(MScheduleDto dto) throws Exception {
		// 予定簿用DAO準備 
		prepareMScheduleDao();
		if (dto == null) {
			return true;
		}
		// 存在チェック
		chkExist(getScheduleInfo(dto.getKCode(), dto.getHizuke()));
		// データの削除
		scheduleDao.delete(dto);
		return chkExistDto(getScheduleInfo(dto.getKCode(), dto.getHizuke()));
	}

	/**
	 * メッセージのセット
	 * @param vo
	 * @throws Exception
	 */
	private void setMessage(ScheduleEditCardVo vo) throws Exception {
		// 予定簿から削除する方法をメッセージにセットする。
		vo.setMessage(CommonConst.MSG_SCHEDULE_EDIT_METHODS);
	}

}
