/*
 * MosP - Mind Open Source Project    http://www.mosp.jp/
 * Copyright (C) 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.common.part;

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

import jp.mosp.common.CommonConst;
import jp.mosp.common.dao.MCodeDao;
import jp.mosp.common.dto.MCodeDto;
import jp.mosp.common.utils.DateUtil;
import jp.mosp.common.utils.NumberUtil;
import jp.mosp.common.utils.StringUtil;
import jp.mosp.common.utils.VariousUtil;

/**
 * MosPのコードに関するPartクラス
 * @author yoshida
 *	@version	0.0.5
 */
public class MosPCodePart extends BasePart {
	
	/**
	 * M_CODE
	 */
	public static final String	TABLE	= MCodeDao.TABLE;
	

	/**
	 * コンストラクタ
	 */
	public MosPCodePart() {
		super();
	}
	
	/**
	 * コンストラクタ
	 * @param partInfo	 Partを利用する際に必要な情報
	 */
	public MosPCodePart(PartInfo partInfo) {
		super(partInfo);
	}
	

	/**
	 * MCodeDaoインスタンス
	 */
	private MCodeDao	codeDao;
	

	/**
	 * MCodeDao取得
	 * @return			初期化済MCodeDaoインスタンス
	 * @throws Exception	例外処理が発生した場合
	 */
	public MCodeDao getMCodeDao() throws Exception {
		if (VariousUtil.isNull(codeDao)) {
			codeDao = (MCodeDao)getPreparedDao(MCodeDao.class.getCanonicalName());
		}
		return codeDao;
	}
	
	/**
	 * キーによる情報の取得
	 * @param tid		コード名
	 * @param tcode		コード
	 * @return	検索結果(DTO)
	 * @throws Exception	例外処理が発生した場合
	 */
	public MCodeDto findForKey(String tid, String tcode) throws Exception {
		return getMCodeDao().findForKey(tid, tcode);
	}
	
	/**
	 * キーによる情報の取得
	 * @param tid		コード名
	 * @return	検索結果(DTO)
	 * @throws Exception	例外処理が発生した場合
	 */
	public MCodeDto findForDto(String tid) throws Exception {
		return getMCodeDao().findForDto(tid);
	}
	
	/**
	 * キーによる情報リスト取得
	 * @param tid		コード名
	 * @param tcode		コード
	 * @return	検索結果(DTOのList)
	 * @throws Exception	例外処理が発生した場合
	 */
	public List<MCodeDto> findForCondition(String tid, String tcode) throws Exception {
		return getMCodeDao().findForCondition(tid, tcode);
	}
	
	/**
	 * キーによる情報の取得
	 * @param tid		コード名
	 * @param tcode		コード
	 * @return	コード変換文字列
	 * @throws Exception	例外処理が発生した場合
	 */
	public String findTchange(String tid, String tcode) throws Exception {
		MCodeDto dto = findForKey(tid, tcode);
		if (VariousUtil.isNotNull(dto)) {
			return dto.getTChange();
		}
		return "";
	}
	
	/**
	 * キーによる情報の取得
	 * @param tid		コード名
	 * @return	コード変換文字列
	 * @throws Exception	例外処理が発生した場合
	 */
	public String findTchange(String tid) throws Exception {
		MCodeDto dto = findForDto(tid);
		if (VariousUtil.isNotNull(dto)) {
			return dto.getTChange();
		}
		return "";
	}
	
	/**
	 * コード区分取得(M_CODE)
	 * @return コード区分リスト
	 * @throws Exception	例外処理が発生した場合
	 */
	public String[][] getMosPCodeArray() throws Exception {
		// コード区分の取得(distinctデータ)
		List<MCodeDto> list = getMCodeDao().findAllTId();
		String[][] aryCode = new String[list.size()][2];
		// Stingの配列に格納
		for (int i = 0; i < aryCode.length; i++) {
			String tId = list.get(i).getTId();
			aryCode[i][0] = tId;
			aryCode[i][1] = tId;
		}
		return aryCode;
	}
	
	/**
	 * コード区分取得(M_CODE)
	 * @param tid コードID
	 * @return コード配列[][]<br>
	 * 			[0]tcode<br>
	 * 			[1]tname<br>
	 * @throws Exception	例外処理が発生した場合
	 */
	public String[][] getMosPCodeArray(String tid) throws Exception {
		// コードの取得
		List<MCodeDto> list = findForCondition(tid);
		String[][] aryCode = new String[list.size()][2];
		// Stingの配列に格納
		for (int i = 0; i < aryCode.length; i++) {
			aryCode[i][0] = list.get(i).getTCode();
			aryCode[i][1] = list.get(i).getTName();
		}
		return aryCode;
	}
	
	/**
	 * コード区分取得(M_CODE)
	 * @param tid		コード名
	 * @param tcode		コード
	 * @return コード配列[][]<br>
	 * 			[0]tcode<br>
	 * 			[1]tname<br>
	 * 			[2]tchange
	 * @throws Exception	例外処理が発生した場合
	 */
	public String[][] getMosPCodeArray(String tid, String tcode) throws Exception {
		// コードの取得
		List<MCodeDto> list = findForCondition(tid, tcode);
		String[][] aryCode = new String[list.size()][3];
		// Stingの配列に格納
		for (int i = 0; i < aryCode.length; i++) {
			aryCode[i] = convArray(list.get(i));
		}
		return aryCode;
	}
	
	/**
	 * コード区分取得(M_CODE)
	 * @param tid		コード名
	 * @param tcode		コード
	 * @return コード配列[][]<br>
	 * 			[0]tcode<br>
	 * 			[1]tname<br>
	 * 			[2]tchange
	 * @throws Exception	例外処理が発生した場合
	 */
	public String[] getMosPCode(String tid, String tcode) throws Exception {
		// コードの取得
		return convArray(findForKey(tid, tcode));
	}
	
	/**
	 * 理由区分取得(M_CODE)
	 * @param tid コードID
	 * @return コード配列[][]<br>
	 * 			[0]tcode<br>
	 * 			[1]tname<br>
	 * @throws Exception	例外処理が発生した場合
	 */
	public String[][] getReasonCodeArray(String tid) throws Exception {
		// コードの取得
		List<MCodeDto> list = getMCodeDao().findForReason(tid);
		String[][] aryCode = new String[list.size()][2];
		// Stingの配列に格納
		for (int i = 0; i < aryCode.length; i++) {
			aryCode[i][0] = list.get(i).getTCode();
			aryCode[i][1] = list.get(i).getTName();
		}
		return aryCode;
	}
	
	/**
	 * コード区分取得(M_CODE)
	 * @return コード配列[][]<br>
	 * 			[0]tcode<br>
	 * 			[1]tname<br>
	 * 			[2]tchange
	 * @param tid コードID
	 * @throws Exception	例外処理が発生した場合
	 */
	public String[] getMosPCode(String tid) throws Exception {
		// コードの取得
		return convArray(findForDto(tid));
	}
	
	/**
	 * 有給休暇支給日数
	 * @return [0]…勤続年数、[1]…支給日数
	 * @throws Exception	例外処理が発生した場合
	 */
	public String[][] getPaidHolidayArray() throws Exception {
		List<MCodeDto> listCode = getPaidHolidayList();
		String[][] aryPaidHolidayDays = new String[listCode.size()][2];
		for (int i = 0; i < aryPaidHolidayDays.length; i++) {
			aryPaidHolidayDays[i][0] = listCode.get(i).getTCode();
			aryPaidHolidayDays[i][1] = listCode.get(i).getTChange();
		}
		return aryPaidHolidayDays;
	}
	
	/**
	 * 有給休暇支給日数情報リスト取得
	 * @return 有給休暇支給日数情報リスト
	 * @throws Exception	例外処理が発生した場合
	 */
	public List<MCodeDto> getPaidHolidayList() throws Exception {
		return getMCodeDao().findForHoliday(CommonConst.TID_PAID_HOLIDAY_SUPPLY);
	}
	
	/**
	 * 勤怠承認機能状況取得(M_CODE)
	 * @return	boolean 	勤怠承認機能の有効無効
	 * @throws Exception	例外処理が発生した場合
	 */
	public boolean isAttendanceApprovalFunction() throws Exception {
		return StringUtil.isFlagOff(getTName(CommonConst.TID_APPROVAL_FUNCTION, CommonConst.TCD_ATTENDANCE_APPROVAL));
	}
	
	/**
	 * パスワード有効期限日数
	 * @return	int		パスワード有効期限日数
	 * @throws Exception	例外処理が発生した場合
	 */
	public int getPasswordTerm() throws Exception {
		int days = 0;
		// コードの取得
		MCodeDto dto = findForDto(CommonConst.TID_PASSWORD_TERM);
		if (VariousUtil.isNotNull(dto)) {
			days = Integer.parseInt(dto.getTChange());
		}
		return days;
	}
	
	/**
	 * 有給繰越情報
	 * @return	String[]	有給繰越情報
	 * <p>
	 * [0]...繰越月、
	 * [1]...繰越日数、
	 * [2]...繰越区分
	 * </p>
	 * @throws Exception 	例外処理が発生した場合
	 */
	public String[] getPaidHolidayInfo() throws Exception {
		return new String[]{
		// 繰越月
			String.valueOf(getCarriedForwardMonth()),
			// 繰越日数
			String.valueOf(getCarriedForwardDays()),
			// 繰越区分
			getCarriedForwardType(), };
	}
	
	/**
	 * 繰越月
	 * @return	繰越月
	 * @throws Exception	例外処理が発生した場合
	 */
	public int getCarriedForwardMonth() throws Exception {
		return NumberUtil.getIntParam(findTchange(CommonConst.TID_PAID_HOLIDAY, CommonConst.TCD_CARRIED_FORWARD_MONTH));
	}
	
	/**
	 * 繰越日数
	 * @return	繰越日数
	 * @throws Exception	例外処理が発生した場合
	 */
	public int getCarriedForwardDays() throws Exception {
		return NumberUtil.getIntParam(findTchange(CommonConst.TID_PAID_HOLIDAY, CommonConst.TCD_CARRIED_FORWARD_DAYS));
	}
	
	/**
	 * 繰越区分
	 * @return	繰越区分
	 * @throws Exception	例外処理が発生した場合
	 */
	public String getCarriedForwardType() throws Exception {
		return findTchange(CommonConst.TID_PAID_HOLIDAY, CommonConst.TCD_CARRIED_FORWARD_TYPE);
	}
	
	/**
	 * 休暇理由配列取得
	 * @since	0.0.2
	 * @return	休暇理由配列
	 * @throws Exception	例外処理が発生した場合
	 */
	public String[][] getHolidayReasonArray() throws Exception {
		String[][] aryHolidayReason = getReasonCodeArray(CommonConst.TID_LEAVE_REASON);
		// 月60時間を超過した場合の代替休暇
		if (useSubstituteHolidayFunction()) {
			aryHolidayReason = StringUtil.addArrayLastRowValue(aryHolidayReason, CommonConst.CODE_SUB_HOLIDAY_REQUEST,
					CommonConst.NAM_SUB_HOLIDAY);
		}
		return aryHolidayReason;
	}
	
	/**
	 * 半休休暇理由配列取得
	 * @return 半休休暇理由配列(時間外代休有効の場合追加)
	 * @throws Exception	例外処理が発生した場合
	 */
	public String[][] getHalfHolidayArray() throws Exception {
		String[][] aryHalfHoliday = getMosPCodeArray(CommonConst.TID_HALF_HOLIDAY_TYPE);
		if (part().mospcode().useSubstituteHolidayFunction()) {
			aryHalfHoliday = StringUtil.addArrayLastRowValue(aryHalfHoliday, CommonConst.CODE_SUB_HOLIDAY_HALF_FLAG,
					CommonConst.NAM_SUB_HOLIDAY_HALF);
		}
		return aryHalfHoliday;
	}
	
	/**
	 * 対象検索コードリスト取得
	 * @param tId			対象検索コード名
	 * @return	検索結果(DTOのList)
	 * @throws Exception	例外処理が発生した場合
	 */
	public List<MCodeDto> findForCondition(String tId) throws Exception {
		return getMCodeDao().findForCondition(tId);
	}
	
	/**
	 * 一次元配列へ変換
	 * @since	0.0.3
	 * @param dto	対象DTO
	 * @return	一次元配列<br>
	 * [0]…tCode
	 * [1]…tName
	 * [2]…tChange
	 */
	public static String[] convArray(MCodeDto dto) {
		if (VariousUtil.isNotNull(dto)) {
			return new String[]{ dto.getTCode(), dto.getTName(), dto.getTChange(), };
		}
		return new String[3];
	}
	
	/**
	 * キーによる情報の取得
	 * @since	0.0.4
	 * @param tid		コード名
	 * @param tcode		コード
	 * @return	コード名称文字列
	 * @throws Exception	例外処理が発生した場合
	 */
	public String getTName(String tid, String tcode) throws Exception {
		MCodeDto dto = findForKey(tid, tcode);
		if (VariousUtil.isNotNull(dto)) {
			return dto.getTName();
		}
		return tcode;
	}
	
	/**
	 * 休暇名称取得
	 * @since	0.0.4
	 * @param tcode		対象休暇理由コード
	 * @return	休暇理由名称
	 * @throws Exception	例外処理が発生した場合
	 */
	public String getHolidayName(String tcode) throws Exception {
		// 月60時間時間外による代休
		if (CommonConst.CODE_SUB_HOLIDAY_REQUEST.equals(tcode)) {
			return CommonConst.NAM_SUB_HOLIDAY;
		}
		return getTName(CommonConst.TID_LEAVE_REASON, tcode);
	}
	
	/**
	 * パスワード有効期限チェック
	 * @param updateDate	更新日時
	 * @return
	 * <p>
	 * 有効期限を超過したらtrue、そうでない場合false
	 * </p>
	 * @throws Exception 	例外処理が発生した場合
	 */
	public boolean isExpirePassWord(Date updateDate) throws Exception {
		int passTerm = getPasswordTerm();
		if (passTerm > 0 && DateUtil.getSystemDate().compareTo(DateUtil.addDay(updateDate, passTerm)) > 0) {
			return true;
		}
		return false;
	}
	
	/**
	 * 限度基準期間配列取得
	 * @since 	0.0.5
	 * @return 限度基準期間配列
	 * @throws Exception  	例外処理が発生した場合
	 */
	public String[][] getLimitStandardTermArray() throws Exception {
		return getMosPCodeArray(CommonConst.TID_LIMIT_STANDARD_TERM);
	}
	
	/**
	 * 協定種類配列取得
	 * @since 	0.0.5
	 * @return 協定種類配列
	 * @throws Exception   	例外処理が発生した場合
	 */
	public String[][] getAgreementTypeArray() throws Exception {
		return getMosPCodeArray(CommonConst.TID_AGREEMENT_TYPE);
	}
	
	/**
	 * 丸め処理コード取得
	 * @since 	0.0.5
	 * @return 丸め処理コード
	 * @throws Exception 	例外処理が発生した場合
	 */
	public String getRoundNumberProcess() throws Exception {
		return findTchange(CommonConst.TID_WORK_SYSTEM, CommonConst.TCD_ROUND_NUMBER);
	}
	
	/**
	 * 月60時間時間外時間機能利用判断
	 * @since 	0.0.5
	 * @return
	 * <p>
	 * 月60時間時間外時間機能を利用する場合true、そうでない場合false
	 * </p>
	 * @throws Exception 	例外処理が発生した場合
	 */
	public boolean useOverTime60HourFunction() throws Exception {
		return StringUtil.isFlagOff(findTchange(CommonConst.TID_WORK_SYSTEM, CommonConst.TCD_OVER_TIME_60_HOUR));
	}
	
	/**
	 * 代休機能利用判断
	 * @since 	0.0.5
	 * @return 
	 * <p>
	 * 代休機能を利用する場合true、そうでない場合false
	 * </p>
	 * @throws Exception 	例外処理が発生した場合
	 */
	public boolean useSubstituteHolidayFunction() throws Exception {
		return useOverTime60HourFunction()
				&& StringUtil.isFlagOff(findTchange(CommonConst.TID_WORK_SYSTEM, CommonConst.TCD_SUBSTITUTE_HOLIDAY));
	}
	
	/**
	 * 時間単位年休機能利用判断
	 * @since 	0.0.5
	 * @return 
	 * <p>
	 * 時間単位年休を利用する場合true、そうでない場合false
	 * </p>
	 * @throws Exception  	例外処理が発生した場合
	 */
	public boolean useHourPaidHolidayFunction() throws Exception {
		return StringUtil.isFlagOff(findTchange(CommonConst.TID_PAID_HOLIDAY,
				CommonConst.TCD_HOUR_PAID_HOLIDAY_FUNCTION));
	}
	
	/**
	 * 年休単位時間取得
	 * @since 	0.0.5
	 * @return 年休単位時間
	 * @throws Exception  	例外処理が発生した場合
	 */
	public int getHourPaidHolidayUnit() throws Exception {
		if (useHourPaidHolidayFunction()) {
			return NumberUtil.getIntParam(findTchange(CommonConst.TID_PAID_HOLIDAY,
					CommonConst.TCD_HOUR_PAID_HOLIDAY_UNIT));
		}
		return 0;
	}
	
	/**
	 * 有給休暇入社月支給フラグ。
	 * @return
	 * <p>
	 * 有給休暇を入社月に支給する場合true、そうでない場合false
	 * </p>
	 * @throws Exception  	例外処理が発生した場合
	 */
	public boolean useProvideEmployMonth() throws Exception {
		return StringUtil.isFlagOn(findTchange(CommonConst.TID_PAID_HOLIDAY, CommonConst.TCD_SUPPLY_MODEL));
	}
	
	/**
	 * 改正労働基準法施行日判断
	 * @param targetDate 対象年月日
	 * @return
	 * <p>
	 * 平成22年4月1日以降の場合true、そうでない場合false
	 * </p>
	 */
	public static boolean afterLegalReformDate(Date targetDate) {
		return DateUtil.getLegalReformDate().compareTo(targetDate) <= 0;
	}
	
}
