package jp.mosp.common.part;

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

import jp.mosp.common.common.MospUtility;
import jp.mosp.kintai.dto.MSyukkinboDto;
import jp.mosp.payroll.dao.MKintaiDao;
import jp.mosp.payroll.dao.MKintaiKinmuDao;
import jp.mosp.payroll.dto.KintaiCompileDto;
import jp.mosp.payroll.dto.MKintaiDto;

/**
 * 勤怠集計用Partクラス
 * @author yoshida
 *	@version	0.0.4
 */
public class KintaiCompilePart extends BasePart {

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

	/**
	 * コンストラクタ
	 * @param partInfo
	 */
	public KintaiCompilePart(PartInfo partInfo) {
		super(partInfo);
	}

	/**
	 * 勤怠集計テーブル用DAOの取得
	 * @since	0.0.3
	 * @return	初期化済みMKintaiDaoインスタンス
	 * @throws Exception
	 */
	public MKintaiDao getMKintaiDao() throws Exception {
		return (MKintaiDao) getPreparedDao(MKintaiDao.class.getCanonicalName());
	}

	/**
	 * 勤務形態別勤怠集計テーブル用DAOの取得
	 * @since	0.0.3
	 * @return	初期化済みMKintaiKinmuDaoインスタンス
	 * @throws Exception
	 */
	public MKintaiKinmuDao getMKintaiKinmuDao() throws Exception {
		return (MKintaiKinmuDao) getPreparedDao(MKintaiKinmuDao.class.getCanonicalName());
	}

	/**
	 * 対象年月勤怠集計情報取得
	 * @param kCode				対象社員コード
	 * @param targetMonth		対象年月
	 * @param attendanceList	対象年月出勤簿リスト
	 * @return	対象年月勤怠集計情報
	 * @throws Exception
	 */
	public KintaiCompileDto getCompiledInfo(
			String kCode,
			List<MSyukkinboDto> attendanceList
	) throws Exception {
		// DTOの初期化
		KintaiCompileDto compileDto = new KintaiCompileDto();
		// 変数宣言、変数の初期化
		// 勤務時間計
		int totalWork = 0;
		// 休憩時間計
		int totalInterbal = 0;
		// 遅刻時間計
		int totalLate = 0;
		// 早退時間計
		int totalLeave = 0;
		// 残業時間計
		int totalOver = 0;
		// 休出時間計
		int totalHolidayWork = 0;
		// 深夜時間計
		int totalLateNight = 0;
		// 出勤日数計
		double totalWorkDays = 0;
		// 出勤回数計
		int totalWorkNumber = 0;
		// 有休日数計
		double totalPaidHoliday = 0;
		// 特別休暇計
		int totalParticularHoliday = 0;
		// 欠勤日数計
		int totalAbsence = 0;
		// 傷病休暇計
		int totalMedicalLeave = 0;
		// 代休日数計
		int totalCompensationDay = 0;
		// 振替休暇計
		int totalTransfer = 0;
		// 其他休暇計
		int totalOther = 0;
		// 遅刻早退数
		int leaveAndLate = 0;
		// 手当
		int syokuji = 0;
		int cyoku1 = 0;
		int cyoku2 = 0;
		int cyoku3 = 0;
		int hoka1 = 0;
		int hoka2 = 0;
		int hoka3 = 0;
		int hoka4 = 0;
		int hoka5 = 0;
		// 時間単位有休数
		int unitHourHoliday = 0;
		/*						
		 *  	2009/08/18	m.yoshida	1.00割増対応
		 */
		// 1.00割増
		int warimasi1 = 0;
		String[][] aryHolidayReason = mospcode().getHolidayReasonArray();
		// 日集計データ取得
		Iterator<MSyukkinboDto> it = attendanceList.iterator();
		// 集計開始
		while (it.hasNext()) {
			MSyukkinboDto dto = it.next();
			// 勤怠項目
			if (KintaiCommonPart.isAvailableWorkType(dto)) {
				// 勤務時間
				totalWork += dto.getKinmuJi();
				// 休憩時間
				totalInterbal += dto.getKyukeiJi();
				// 遅刻時間
				totalLate += dto.getTiJikan();
				// 早退時間
				totalLeave += dto.getSoJikan();
				// 残業時間
				totalOver += dto.getZaJikan();
				// 休出時間
				totalHolidayWork += dto.getKsJikan();
				// 深夜時間
				totalLateNight += dto.getSnJikan();
				// 出勤日数
				if (dto.getKinmuJi() > 0) {
					totalWorkDays++;
					totalWorkNumber++;
				}
				// 遅刻早退数
				if (dto.getTiJikan() > 0 || dto.getSoJikan() > 0) {
					leaveAndLate++;
				}
				// 手当
				syokuji += dto.getSyokuji();
				cyoku1 += dto.getCyoku1();
				cyoku2 += dto.getCyoku2();
				cyoku3 += dto.getCyoku3();
				hoka1 += dto.getHoka1();
				hoka2 += dto.getHoka2();
				hoka3 += dto.getHoka3();
				hoka4 += dto.getHoka4();
				hoka5 += dto.getHoka5();
				// 半休
				if (KintaiCommonPart.isStartHalfHoliday(dto) 
						|| KintaiCommonPart.isQuitHalfHoliday(dto)
				) {
					totalPaidHoliday += 0.5;
					totalWorkDays -= 0.5;
				}
				// 二時間年休数
				unitHourHoliday += dto.getNijiKyu();
				/*						
				 *  	2009/08/18	m.yoshida	1.00割増対応
				 */
				// 1.00割増
				warimasi1 += dto.getWarimasi1();
			} else {
				// 休暇項目
				if (KintaiCommonPart.isHoliday(dto)) {
					if (KintaiCommonPart.isAllHoliday(dto, aryHolidayReason)) {
						// 有給休暇（m_code, 休暇理由, tcode="0"）
						totalPaidHoliday++;
					} else if (dto.getKKRiyuu().equals(aryHolidayReason[1][0])) {
						// 特別休暇（m_code, 休暇理由, tcode="1"）
						totalParticularHoliday++;
					} else if (dto.getKKRiyuu().equals(aryHolidayReason[2][0])) {
						// 欠勤日数（m_code, 休暇理由, tcode="2"）
						totalAbsence++;
					} else if (dto.getKKRiyuu().equals(aryHolidayReason[3][0])) {
						// 傷病休暇（m_code, 休暇理由, tcode="3"）
						totalMedicalLeave++;
					} else if (KintaiCommonPart.isSubstituteHoliday(dto, aryHolidayReason)) {
						// 代休日数（m_code, 休暇理由, tcode="4"）
						totalCompensationDay++;
					} else if (dto.getKKRiyuu().equals(aryHolidayReason[5][0])) {
						// 振替休暇（m_code, 休暇理由, tcode="5"）
						totalTransfer++;
					} else {
						// 其他休暇（m_code, 休暇理由, tcode="6"より上）
						totalOther++;
					}
				}
			}
		}
		// 出勤日数
		compileDto.setTotalWorkDays(totalWorkDays);
		// 出勤回数
		compileDto.setTotalWorkNumber(totalWorkNumber);
		// 勤務時間合計
		compileDto.setTotalWork(totalWork);
		// 休憩時間合計
		compileDto.setTotalInterbal(totalInterbal);
		// 有給休暇日数
		compileDto.setTotalPaidHoliday(totalPaidHoliday);
		// 特別休暇日数
		compileDto.setTotalParticularHoliday(totalParticularHoliday);
		// 欠勤休暇日数
		compileDto.setTotalAbsence(totalAbsence);
		// 傷病休暇日数
		compileDto.setTotalMedicalLeave(totalMedicalLeave);
		// 代休日数
		compileDto.setTotalCompensationDay(totalCompensationDay);
		// 振替休暇日数
		compileDto.setTotalTransfer(totalTransfer);
		// 其他休暇日数
		compileDto.setTotalOther(totalOther);
		// 遅刻早退数
		compileDto.setLeaveAndLate(leaveAndLate);
		// 遅刻時間
		compileDto.setTotalLate(totalLate);
		// 早退時間
		compileDto.setTotalLeave(totalLeave);
		// 残業時間合計
		compileDto.setTotalOver(totalOver);
		// 休出時間合計
		compileDto.setTotalHolidayWork(totalHolidayWork);
		// 深夜時間合計
		compileDto.setTotalLateNight(totalLateNight);
		// 皆勤（欠勤、特別休暇、傷病、遅刻早退数の合計）
		if ((totalAbsence + totalParticularHoliday + totalMedicalLeave + leaveAndLate) == 0
				&& totalWorkDays != 0
		) {
			compileDto.setApplyAttendanceAllowance(true);
		}
		// 役職による手当支給設定
		if (!PartManager.position(partInfo()).isApplyAttendanceAllowance(kCode)) {
			compileDto.setApplyAttendanceAllowance(false);
		}
		// 手当
		// 食事手当合計
		compileDto.setSyokuji(syokuji);
		// １直手当合計
		compileDto.setCyoku1(cyoku1);
		// ２直手当合計
		compileDto.setCyoku2(cyoku2);
		// ３直手当合計
		compileDto.setCyoku3(cyoku3);
		// その他手当１合計
		compileDto.setHoka1(hoka1);
		// その他手当２合計
		compileDto.setHoka2(hoka2);
		// その他手当３合計
		compileDto.setHoka3(hoka3);
		// その他手当４合計
		compileDto.setHoka4(hoka4);
		// その他手当５合計
		compileDto.setHoka5(hoka5);
		// 時間単位年休合計
		compileDto.setUnitHourHoliday(unitHourHoliday);
		/*						
		 *  	2009/08/18	m.yoshida	1.00割増対応
		 */
		// 1.00割増時間合計
		compileDto.setWarimasi1(warimasi1);
		return compileDto;
	}

	/**
	 * 対象年月勤怠集計情報変換
	 * @param kCode			対象社員コード
	 * @param targetMonth	対象年月日
	 * @param dto			対象年月勤怠集計情報DTO
	 * @return	勤怠集計情報
	 * @throws Exception
	 */
	public MKintaiDto convCompileToKintai(
			String kCode,
			Date targetMonth,
			KintaiCompileDto dto
	) throws Exception {
		// DTOの初期化
		MKintaiDto mKintaiDto = new MKintaiDto();
		// DTOに値をセット
		mKintaiDto.setKCode(kCode);
		// 支給年月日
		Date calcPaymentDate = calculate().getCalcPayment(targetMonth);
		// 支給年月
		mKintaiDto.setSikyuYM(DatePart.convDateToStringYearMonthShort(targetMonth));
		// 支給年
		mKintaiDto.setSNen(MospUtility.getYear(calcPaymentDate));
		// 支給月
		mKintaiDto.setSTuki(MospUtility.getMonth(calcPaymentDate));
		// 支給日
		mKintaiDto.setSHi(MospUtility.getDay(calcPaymentDate));
		if (VariousPart.chkExistDto(dto)) {
			// 出勤日数
			mKintaiDto.setSNissu(dto.getTotalWorkDays());
			// 出勤回数
			mKintaiDto.setSKaisu(dto.getTotalWorkNumber());
			// 勤務時間合計
			mKintaiDto.setKinmuJi(dto.getTotalWork());
			// 休憩時間合計
			mKintaiDto.setKyukeiJi(dto.getTotalInterbal());
			// 有給休暇日数
			mKintaiDto.setYukyu(dto.getTotalPaidHoliday());
			// 特別休暇日数
			mKintaiDto.setTokuKyu(dto.getTotalParticularHoliday());
			// 欠勤休暇日数
			mKintaiDto.setKekkin(dto.getTotalAbsence());
			// 傷病休暇日数
			mKintaiDto.setSKekkin(dto.getTotalMedicalLeave());
			// 代休日数
			mKintaiDto.setDaiKyu(dto.getTotalCompensationDay());
			// 振替休暇日数
			mKintaiDto.setFurikae(dto.getTotalTransfer());
			// 其他休暇日数
			mKintaiDto.setSonota(dto.getTotalOther());
			// 遅刻早退数
			mKintaiDto.setTiSoKai(dto.getLeaveAndLate());
			// 遅刻早退時間合計
			mKintaiDto.setTiJikan(dto.getTotalLate() + dto.getTotalLeave());
			// 残業時間合計
			mKintaiDto.setZaJikan(dto.getTotalOver());
			// 休出時間合計
			mKintaiDto.setKsJikan(dto.getTotalHolidayWork());
			// 深夜時間合計
			mKintaiDto.setSnJikan(dto.getTotalLateNight());
			// 皆勤
			if (dto.isApplyAttendanceAllowance()) {
				mKintaiDto.setKaikin(1);
			}
			// 手当
			// 食事手当合計
			mKintaiDto.setSyokujiKaisu(dto.getSyokuji());
			// １直手当合計
			mKintaiDto.setCyokuKaisu1(dto.getCyoku1());
			// ２直手当合計
			mKintaiDto.setCyokuKaisu2(dto.getCyoku2());
			// ３直手当合計
			mKintaiDto.setCyokuKaisu3(dto.getCyoku3());
			// その他手当１合計
			mKintaiDto.setHokaKaisu1(dto.getHoka1());
			// その他手当２合計
			mKintaiDto.setHokaKaisu2(dto.getHoka2());
			// その他手当３合計
			mKintaiDto.setHokaKaisu3(dto.getHoka3());
			// その他手当４合計
			mKintaiDto.setHokaKaisu4(dto.getHoka4());
			// その他手当５合計
			mKintaiDto.setHokaKaisu5(dto.getHoka5());
			// 二時間年休合計
			mKintaiDto.setNijiKyu(dto.getUnitHourHoliday());
			/*						
			 *  	2009/08/18	m.yoshida	1.00割増対応
			 */
			// 1.00割増
			mKintaiDto.setWarimasi1(dto.getWarimasi1());
		}
		return mKintaiDto;
	}

	/**
	 * 勤怠月集計
	 * @param kCode				対象社員コード
	 * @param targetMonth		対象年月
	 * @return	勤怠月集計
	 * @throws Exception
	 */
	public MKintaiDto getCompiledInfo(
			String kCode,
			Date targetMonth,
			List<MSyukkinboDto> attendanceList
	) throws Exception {
		// 対象年月勤怠集計情報
		return convCompileToKintai(kCode, targetMonth, getCompiledInfo(kCode, attendanceList));
	}

	/**
	 * 承認・未承認件数作成
	 * @since	0.0.2
	 * @return [0]…承認件数、[1]…未承認件数、[2]…出勤件数
	 * @throws Exception
	 */
	public static int[] makeApprovalNumber(List<MSyukkinboDto> attendanceList) {
		// 配列初期化
		int number[] = {0, 0, 0};
		// データの設定
		Iterator<MSyukkinboDto> it = attendanceList.iterator();
		// 出勤件数
		number[2] = attendanceList.size();
		while (it.hasNext()) {
			MSyukkinboDto dto = it.next();
			// 一次承認、二次承認
			if (KintaiApprovalPart.is2ndApproved(dto)) {
				number[0]++;
			} else {
				number[1]++;
			}
			break;
		}
		return number;
	}

}
