/*
 * 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 Affero General Public License
 * as published by the Free Software Foundation, either version 3
 * 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 Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * 
 */
package jp.mosp.time.bean.impl;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import jp.mosp.framework.base.BaseDtoInterface;
import jp.mosp.framework.base.MospException;
import jp.mosp.framework.base.MospParams;
import jp.mosp.framework.utils.DateUtility;
import jp.mosp.platform.bean.human.HumanReferenceBeanInterface;
import jp.mosp.platform.bean.human.impl.HumanSearchBean;
import jp.mosp.platform.bean.workflow.WorkflowIntegrateBeanInterface;
import jp.mosp.platform.constant.PlatformConst;
import jp.mosp.platform.constant.PlatformMessageConst;
import jp.mosp.platform.dto.human.HumanDtoInterface;
import jp.mosp.platform.dto.workflow.WorkflowDtoInterface;
import jp.mosp.time.bean.ApprovalInfoReferenceBeanInterface;
import jp.mosp.time.bean.AttendanceReferenceBeanInterface;
import jp.mosp.time.bean.DifferenceRequestReferenceBeanInterface;
import jp.mosp.time.bean.HolidayRequestReferenceBeanInterface;
import jp.mosp.time.bean.OvertimeRequestReferenceBeanInterface;
import jp.mosp.time.bean.RequestSearchBeanInterface;
import jp.mosp.time.bean.SubHolidayRequestReferenceBeanInterface;
import jp.mosp.time.constant.TimeConst;
import jp.mosp.time.dao.settings.HolidayDaoInterface;
import jp.mosp.time.dto.settings.AttendanceDtoInterface;
import jp.mosp.time.dto.settings.DifferenceRequestDtoInterface;
import jp.mosp.time.dto.settings.HolidayDtoInterface;
import jp.mosp.time.dto.settings.HolidayRequestDtoInterface;
import jp.mosp.time.dto.settings.ManagementRequestListDtoInterface;
import jp.mosp.time.dto.settings.OvertimeRequestDtoInterface;
import jp.mosp.time.dto.settings.SubHolidayRequestDtoInterface;
import jp.mosp.time.dto.settings.WorkOnHolidayRequestDtoInterface;
import jp.mosp.time.dto.settings.impl.ManagementRequestListDto;

/**
 * 申請検索クラス。
 */
public class RequestSearchBean extends HumanSearchBean implements RequestSearchBeanInterface {
	
	/**
	 * 区切文字(申請情報詳細)。
	 */
	public static final String							SEPARATOR_REQUEST_INFO	= " ";
	
	/**
	 * 休暇種別管理DAO
	 */
	protected HolidayDaoInterface						holidayDao;
	
	/**
	 * ワークフロー統括
	 */
	protected WorkflowIntegrateBeanInterface			workflowIntegrate;
	
	/**
	 * 勤怠データ参照
	 */
	protected AttendanceReferenceBeanInterface			attendanceReference;
	
	/**
	 * 承認情報参照クラス
	 */
	protected ApprovalInfoReferenceBeanInterface		approvalInfoReference;
	
	/**
	 * 人事マスタ参照クラス
	 */
	protected HumanReferenceBeanInterface				humanReference;
	
	/**
	 * 残業申請データ参照クラス。
	 */
	protected OvertimeRequestReferenceBeanInterface		overtimeRequestReference;
	
	/**
	 * 休暇申請データ参照クラス。
	 */
	protected HolidayRequestReferenceBeanInterface		holidayRequestReference;
	
	/**
	 * 休日出勤申請参照クラス
	 */
	protected WorkOnHolidayRequestReferenceBean			workOnHolidayRequestReference;
	
	/**
	 * 代休申請データ参照クラス。
	 */
	protected SubHolidayRequestReferenceBeanInterface	subHolidayRequestReference;
	
	/**
	 * 時差出勤申請参照クラス
	 */
	protected DifferenceRequestReferenceBeanInterface	differenceRequestReference;
	
	/**
	 * 開始年月日。
	 */
	private Date										startDate;
	
	/**
	 * 終了年月日。
	 */
	private Date										endDate;
	
	/**
	 * 申請カテゴリ。
	 */
	private String										approvalType;
	
	/**
	 * 状態。
	 */
	private String										state;
	

	/**
	 * コンストラクタ。
	 */
	public RequestSearchBean() {
		// 処理無し
	}
	
	/**
	 * コンストラクタ。
	 * @param mospParams MosPパラメータクラス。
	 * @param connection DBコネクション。
	 */
	public RequestSearchBean(MospParams mospParams, Connection connection) {
		super(mospParams, connection);
	}
	
	@Override
	public void initBean() throws MospException {
		// 継承元のメソッドを実行
		super.initBean();
		// 承認参照クラス
		approvalInfoReference = (ApprovalInfoReferenceBeanInterface)createBean(ApprovalInfoReferenceBeanInterface.class);
		// ワークフロー参照クラス
		workflowIntegrate = (WorkflowIntegrateBeanInterface)createBean(WorkflowIntegrateBeanInterface.class);
		// 休暇種別管理DAO
		holidayDao = (HolidayDaoInterface)createDao(HolidayDaoInterface.class);
		// 勤怠データ参照クラス
		attendanceReference = (AttendanceReferenceBeanInterface)createBean(AttendanceReferenceBeanInterface.class);
		// 人事マスタ参照クラス
		humanReference = (HumanReferenceBeanInterface)createBean(HumanReferenceBeanInterface.class);
		// 残業申請参照クラス
		overtimeRequestReference = (OvertimeRequestReferenceBeanInterface)createBean(OvertimeRequestReferenceBeanInterface.class);
		// 休暇申請参照クラス
		holidayRequestReference = (HolidayRequestReferenceBeanInterface)createBean(HolidayRequestReferenceBeanInterface.class);
		// 休日出勤申請参照クラス
		workOnHolidayRequestReference = (WorkOnHolidayRequestReferenceBean)createBean(WorkOnHolidayRequestReferenceBean.class);
		// 代休申請参照クラス
		subHolidayRequestReference = (SubHolidayRequestReferenceBeanInterface)createBean(SubHolidayRequestReferenceBeanInterface.class);
		// 時差出勤申請参照クラス
		differenceRequestReference = (DifferenceRequestReferenceBeanInterface)createBean(DifferenceRequestReferenceBeanInterface.class);
	}
	
	@Override
	public List<ManagementRequestListDtoInterface> getSearchList() throws MospException {
		// 未承認一覧
		List<ManagementRequestListDtoInterface> list = new ArrayList<ManagementRequestListDtoInterface>();
		// 勤怠データDTO
		AttendanceDtoInterface attendanceDto = null;
		// 残業申請DTO
		OvertimeRequestDtoInterface overtimeDto = null;
		// 休暇申請DTO
		HolidayRequestDtoInterface holidayDto = null;
		// 休日出勤申請DTO 
		WorkOnHolidayRequestDtoInterface workOnHolidayDto = null;
		// 代休申請DTO
		SubHolidayRequestDtoInterface subHolidayDto = null;
		// 時差出勤申請DTO 
		DifferenceRequestDtoInterface differenceDto = null;
		
		// 検索条件設定
		setEmployeeCodeType(PlatformConst.SEARCH_FORWARD_MATCH);
		setStateType(PlatformConst.EMPLOYEE_STATE_PRESENCE);
		// 申請者情報の取得
		List<HumanDtoInterface> humanList = search();
		String personaId = "";
		// 承認対象のワークフロー一覧
		List<WorkflowDtoInterface> workflowList = new ArrayList<WorkflowDtoInterface>();
		Collection<WorkflowDtoInterface> workflowCollection = workflowIntegrate.getList(mospParams.getUser()
			.getPersonalId(), startDate, endDate, approvalType);
		for (WorkflowDtoInterface dto : workflowCollection) {
			long workflow = dto.getWorkflow();
			Date requestDate = null;
			if (TimeConst.CODE_FUNCTION_WORK_MANGE.equals(dto.getFunctionCode())) {
				// 勤怠
				AttendanceDtoInterface requestDto = attendanceReference.findForWorkflow(workflow);
				if (requestDto == null) {
					continue;
				}
				requestDate = requestDto.getWorkDate();
			} else if (TimeConst.CODE_FUNCTION_OVER_WORK.equals(dto.getFunctionCode())) {
				// 残業申請
				OvertimeRequestDtoInterface requestDto = overtimeRequestReference.findForWorkflow(workflow);
				if (requestDto == null) {
					continue;
				}
				requestDate = requestDto.getRequestDate();
			} else if (TimeConst.CODE_FUNCTION_VACATION.equals(dto.getFunctionCode())) {
				// 休暇申請
				HolidayRequestDtoInterface requestDto = holidayRequestReference.findForWorkflow(workflow);
				if (requestDto == null) {
					continue;
				}
				requestDate = requestDto.getRequestStartDate();
			} else if (TimeConst.CODE_FUNCTION_WORK_HOLIDAY.equals(dto.getFunctionCode())) {
				// 休日出勤申請
				WorkOnHolidayRequestDtoInterface requestDto = workOnHolidayRequestReference.findForWorkflow(workflow);
				if (requestDto == null) {
					continue;
				}
				requestDate = requestDto.getRequestDate();
			} else if (TimeConst.CODE_FUNCTION_COMPENSATORY_HOLIDAY.equals(dto.getFunctionCode())) {
				// 代休申請
				SubHolidayRequestDtoInterface requestDto = subHolidayRequestReference.findForWorkflow(workflow);
				if (requestDto == null) {
					continue;
				}
				requestDate = requestDto.getRequestDate();
			} else if (TimeConst.CODE_FUNCTION_DIFFERENCE.equals(dto.getFunctionCode())) {
				// 時差出勤申請
				DifferenceRequestDtoInterface requestDto = differenceRequestReference.findForWorkflow(workflow);
				if (requestDto == null) {
					continue;
				}
				requestDate = requestDto.getRequestDate();
			}
			if (requestDate == null) {
				continue;
			}
			if (!requestDate.before(startDate) && !requestDate.after(endDate)) {
				workflowList.add(dto);
			}
		}
		// 申請の取得
		for (WorkflowDtoInterface workflowDto : workflowList) {
			// 申請情報
			BaseDtoInterface requestDto = approvalInfoReference.getRequestDtoForWorkflow(workflowDto.getWorkflow(),
					false);
			long tmdManagementRequestListId = 0;
			String requestInfo = "";
			Date requestDate = null;
			// カテゴリ別に表示する
			// 勤怠承認状況
			if (requestDto instanceof AttendanceDtoInterface) {
				attendanceDto = (AttendanceDtoInterface)requestDto;
				personaId = attendanceDto.getPersonalId();
				tmdManagementRequestListId = attendanceDto.getTmdAttendanceId();
				requestDate = attendanceDto.getWorkDate();
				requestInfo = getAttendanceInfo(attendanceDto);
			}
			// 残業承認状況
			if (requestDto instanceof OvertimeRequestDtoInterface) {
				overtimeDto = (OvertimeRequestDtoInterface)requestDto;
				personaId = overtimeDto.getPersonalId();
				tmdManagementRequestListId = overtimeDto.getTmdOvertimeRequestId();
				requestDate = overtimeDto.getRequestDate();
				requestInfo = getOvertimeRequestInfo(overtimeDto);
			}
			// 休暇申請承認状況
			if (requestDto instanceof HolidayRequestDtoInterface) {
				holidayDto = (HolidayRequestDtoInterface)requestDto;
				personaId = holidayDto.getPersonalId();
				tmdManagementRequestListId = holidayDto.getTmdHolidayRequestId();
				requestDate = holidayDto.getRequestStartDate();
				requestInfo = getHolidayRequestInfo(holidayDto);
			}
			// 休日出勤承認状況
			if (requestDto instanceof WorkOnHolidayRequestDtoInterface) {
				workOnHolidayDto = (WorkOnHolidayRequestDtoInterface)requestDto;
				personaId = workOnHolidayDto.getPersonalId();
				tmdManagementRequestListId = workOnHolidayDto.getTmdWorkOnHolidayRequestId();
				requestDate = workOnHolidayDto.getRequestDate();
				requestInfo = workOnHolidayRequestReference.getWorkOnHolidayInfo(workOnHolidayDto);
			}
			// 代休承認状況
			if (requestDto instanceof SubHolidayRequestDtoInterface) {
				subHolidayDto = (SubHolidayRequestDtoInterface)requestDto;
				personaId = subHolidayDto.getPersonalId();
				tmdManagementRequestListId = subHolidayDto.getTmdSubHolidayRequestId();
				requestDate = subHolidayDto.getRequestDate();
				requestInfo = getSubHolidayRequestInfo(subHolidayDto);
			}
			// 時差出勤承認状況
			if (requestDto instanceof DifferenceRequestDtoInterface) {
				differenceDto = (DifferenceRequestDtoInterface)requestDto;
				personaId = differenceDto.getPersonalId();
				tmdManagementRequestListId = differenceDto.getTmdDifferenceRequestId();
				requestDate = differenceDto.getRequestDate();
				requestInfo = differenceRequestReference.getDifferenceRequestInfo(differenceDto);
			}
			boolean targetFlag = false;
			for (HumanDtoInterface humanDto : humanList) {
				if (humanDto.getPersonalId().equals(personaId)) {
					targetFlag = true;
					break;
				}
			}
			if (!targetFlag) {
				continue;
			}
			// DTOの準備
			ManagementRequestListDtoInterface dto = new ManagementRequestListDto();
			dto.setTmdManagementRequestListId(tmdManagementRequestListId);
			dto.setRequestDate(requestDate);
			// 締日の取得
			Date startDate = DateUtility.getFirstDateOfMonth(targetDate);
			Date endDate = DateUtility.getLastDateOfMonth(targetDate);
			if (!requestDate.before(endDate)) {
				continue;
			}
			if (requestDate.before(startDate)) {
				continue;
			}
			dto.setRequestInfo(requestInfo);
			// 人事情報
			getHumanInfo(personaId, dto);
			// 申請内容
			dto.setRequestType(workflowDto.getFunctionCode());
			// ワークフロー
			dto.setStage(workflowDto.getWorkflowStage());
			dto.setState(workflowDto.getWorkflowStatus());
			dto.setWorkflow(workflowDto.getWorkflow());
			// 状態を条件にしてlistに設定する
			boolean addFlag = false;
			// 状態の検索
			if ("1".equals(state)) {
				// 未承認
				addFlag = PlatformConst.CODE_STATUS_APPLY.equals(dto.getState())
						|| PlatformConst.CODE_STATUS_APPROVED.equals(dto.getState());
			} else if ("2".equals(state)) {
				// 承認済
				addFlag = dto.getStage() == 10 && PlatformConst.CODE_STATUS_COMPLETE.equals(dto.getState());
			} else if ("3".equals(state)) {
				// 差戻
				addFlag = PlatformConst.CODE_STATUS_REVERT.equals(dto.getState());
			} else if (state.isEmpty()) {
				addFlag = true;
			}
			if (addFlag) {
				list.add(dto);
			}
		}
		return list;
	}
	
	@Override
	public void setStartDate(Date startDate) {
		this.startDate = startDate;
	}
	
	@Override
	public void setEndDate(Date endDate) {
		this.endDate = endDate;
	}
	
	@Override
	public void setApprovalType(String approvalType) {
		this.approvalType = approvalType;
	}
	
	@Override
	public void setState(String state) {
		this.state = state;
	}
	
	/**
	 * 申請情報詳細の設定
	 * @param dto 勤怠情報DTO
	 * @return 申請情報詳細
	 * @throws MospException SQLの作成に失敗した場合、或いはSQL例外が発生した場合
	 */
	public String getAttendanceInfo(AttendanceDtoInterface dto) throws MospException {
		StringBuffer infoStringBuffer = new StringBuffer();
		// 勤怠設定で表示する内容は無し
		infoStringBuffer.append("");
		return infoStringBuffer.toString();
	}
	
	/**
	 * 申請情報詳細の設定
	 * @param dto 残業申請DTO
	 * @return 申請情報詳細
	 */
	public String getOvertimeRequestInfo(OvertimeRequestDtoInterface dto) {
		// 表示例 予定:2時間30分　理由:顧客サポート
		StringBuffer sb = new StringBuffer();
		// 予定
		sb.append(mospParams.getName("Schedule") + mospParams.getName("Colon") + (dto.getRequestTime() / 60)
				+ mospParams.getName("Time") + (dto.getRequestTime() % 60) + mospParams.getName("Minutes"));
		// 空欄
		sb.append(" ");
		// 理由
		sb.append(mospParams.getName("Reason") + mospParams.getName("Colon") + dto.getRequestReason());
		return sb.toString();
	}
	
	/**
	 * 申請情報詳細の設定
	 * @param dto 休暇申請DTO
	 * @return 申請情報詳細
	 * @throws MospException SQLの作成に失敗した場合、或いはSQL例外が発生した場合
	 */
	public String getHolidayRequestInfo(HolidayRequestDtoInterface dto) throws MospException {
		// 表示例 終了日：2010/1/1　結婚休暇
		StringBuffer sb = new StringBuffer();
		// 終了日
		sb.append(mospParams.getName("End") + mospParams.getName("Day") + mospParams.getName("Colon"));
		// 期間
		long periodCalc = dto.getRequestEndDate().getTime() - dto.getRequestStartDate().getTime();
		int periodNun = DateUtility.getDay(new Date(periodCalc));
		if (1 == periodNun) {
			// 範囲期間が1日
			sb.append(DateUtility.getStringDate(dto.getRequestStartDate()));
		} else if (2 <= periodNun) {
			// 範囲期間が2日以上
			sb.append(DateUtility.getStringDate(dto.getRequestEndDate()));
		} else {
			// 例外
		}
		// 空欄
		sb.append(SEPARATOR_REQUEST_INFO);
		// 休暇種別管理DTO取得
		HolidayDtoInterface holidayDto = holidayDao.findForKey(dto.getHolidayType2(), dto.getRequestStartDate(), dto
			.getHolidayType1());
		if (holidayDto != null) {
			// 休暇名称
			sb.append(holidayDto.getHolidayName());
			sb.append(SEPARATOR_REQUEST_INFO);
		}
		// 休暇範囲設定
		sb.append(mospParams.getProperties().getCodeItemName(TimeConst.CODE_HOLIDAY_TYPE3_RANGE1,
				String.valueOf(dto.getHolidayRange())));
		return sb.toString();
	}
	
	/**
	 * 申請情報詳細の設定
	 * @param dto 代休申請DTO
	 * @return 申請情報詳細
	 * @throws MospException 例外処理発生時
	 */
	public String getSubHolidayRequestInfo(SubHolidayRequestDtoInterface dto) throws MospException {
		// 表示例 休出:2010/12/1 勤務7時間00分
		StringBuffer sb = new StringBuffer();
		int type = dto.getWorkDateSubHolidayType();
		if (type == 1 || type == 2) {
			// 休出
			sb.append(mospParams.getName("WorkingHoliday"));
		} else if (type == 3) {
			// 深夜
			sb.append(mospParams.getName("Midnight"));
		}
		sb.append(mospParams.getName("Colon"));
		sb.append(DateUtility.getStringDate(dto.getWorkDate()));
		// 空欄
		sb.append(" ");
		sb.append(mospParams.getName("Work"));
		sb.append(mospParams.getName("Colon"));
		AttendanceDtoInterface attendanceDto = attendanceReference
			.findForKey(dto.getPersonalId(), dto.getWorkDate(), 1);
		if (attendanceDto == null) {
			sb.append(0);
			sb.append(mospParams.getName("Time"));
			sb.append("00");
			sb.append(mospParams.getName("Minutes"));
		} else {
			sb.append(attendanceDto.getWorkTime() / 60);
			sb.append(mospParams.getName("Time"));
			sb.append(getMinute(attendanceDto.getWorkTime()));
			sb.append(mospParams.getName("Minutes"));
		}
		// 休暇範囲設定
		sb.append(SEPARATOR_REQUEST_INFO);
		sb.append(mospParams.getProperties().getCodeItemName(TimeConst.CODE_HOLIDAY_TYPE3_RANGE1,
				String.valueOf(dto.getHolidayRange())));
		return sb.toString();
	}
	
	/**
	 * 個人IDから社員コード、社員名、所属を取得する。<br>
	 * @param personalId 個人ID
	 * @param dto 申請情報確認一覧DTO
	 * @throws MospException 例外発生時
	 */
	public void getHumanInfo(String personalId, ManagementRequestListDtoInterface dto) throws MospException {
		// 取得したユーザIDとシステム日付から個人IDを取得する
		HumanDtoInterface humanDto = humanReference.getHumanInfo(personalId, targetDate);
		// Listから引数で取得した個人IDと一致するものがあるかチェックする
		if (humanDto == null) {
			// 取得したユーザIDに該当する人事マスタのデータがNULLなら処理終了
			mospParams.addErrorMessage(PlatformMessageConst.MSG_NO_ITEM, mospParams.getName("Employee"), null);
			return;
		}
		// 人事情報を設定する
		dto.setEmployeeCode(humanDto.getEmployeeCode());
		dto.setLastName(humanDto.getLastName());
		dto.setFirstName(humanDto.getFirstName());
		dto.setSectionCode(humanDto.getSectionCode());
		return;
	}
	
	/**
	 * 分取得。
	 * @param time 時間
	 * @return 分
	 */
	protected String getMinute(int time) {
		String min = Integer.toString(time % 60);
		if (min.length() == 1) {
			return 0 + min;
		}
		return min;
	}
	
}
