/*
 * MosP - Mind Open Source Project         http://www.mosp.jp/
 * Copyright (C) 1987-2009 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.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import jp.mosp.common.CommonConst;

import jp.mosp.common.common.MospException;
import jp.mosp.common.dto.HumanBasisDtoInterface;
import jp.mosp.common.dto.KintaiCommonDtoInterface;
import jp.mosp.human.dto.MKihonDto;

import jp.mosp.workflow.dao.AttendanceRouteDao;
import jp.mosp.workflow.dao.PmAttendanceDao;
import jp.mosp.workflow.dto.AttendanceRouteDto;
import jp.mosp.workflow.dto.PmAttendanceDto;

/**
 * 勤怠承認用Partクラス
 * @author yoshida
 *	@version	0.0.6
 */
public class KintaiApprovalPart extends BasePart {

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

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

	/**
	 * 勤怠承認用ルートテーブル用のDAO取得
	 * @since	0.0.2
	 * @return	初期化済みAttendanceRouteDaoインスタンス
	 * @throws Exception
	 */
	public AttendanceRouteDao getAttendanceRouteDao() throws Exception {
		return (AttendanceRouteDao) getPreparedDao(AttendanceRouteDao.class.getCanonicalName());
	}

	/**
	 * 勤怠承認ルートマスタテーブル用のDAO取得
	 * @since	0.0.2
	 * @return	初期化済みPmAttendanceDaoインスタンス
	 * @throws Exception
	 */
	public PmAttendanceDao getPmAttendanceDao() throws Exception {
		return (PmAttendanceDao) getPreparedDao(PmAttendanceDao.class.getCanonicalName());
	}

	/**
	 * 出勤簿申請中フラグ取得
	 * @param dto		対象出勤簿DTO
	 * @return
	 * <p>
	 * 申請中ならtrue、そうでない場合false
	 * </p>
	 */
	public static boolean isRequest(String snriyuu) {
		return VariousPart.getApprovalStatusCodeArray()[0].equals(snriyuu);
	}

	/**
	 * 出勤簿申請中フラグ取得
	 * @param dto		対象出勤簿DTO
	 * @return
	 * <p>
	 * 申請中ならtrue、そうでない場合false
	 * </p>
	 */
	public static boolean isRequest(KintaiCommonDtoInterface dto) throws Exception {
		if (VariousPart.chkExistObject(dto)) {
			return isRequest(dto.getSnRiyuu());
		}
		return false;
	}

	/**
	 * 出勤簿一次承認済フラグ取得
	 * @param dto		対象出勤簿DTO
	 * @return
	 * <p>
	 * 承認済ならtrue、そうでない場合false
	 * </p>
	 */
	public static boolean is1stApproved(String snriyuu) {
		return VariousPart.getApprovalStatusCodeArray()[1].equals(snriyuu);
	}

	/**
	 * 出勤簿一次承認済フラグ取得
	 * @param dto		対象出勤簿DTO
	 * @return
	 * <p>
	 * 承認済ならtrue、そうでない場合false
	 * </p>
	 * @throws Exception
	 */
	public static boolean is1stApproved(KintaiCommonDtoInterface dto) throws Exception {
		if (VariousPart.chkExistObject(dto)) {
			return is1stApproved(dto.getSnRiyuu());
		}
		return false;
	}

	/**
	 * 出勤簿一次差戻フラグ取得
	 * @since	0.0.4
	 * @param dto		対象出勤簿DTO
	 * @return
	 * <p>
	 * 一次差戻ならtrue、そうでない場合false
	 * </p>
	 */
	public static boolean is1stReturned(String snriyuu) {
		return VariousPart.getApprovalStatusCodeArray()[2].equals(snriyuu);
	}

	/**
	 * 出勤簿一次差戻フラグ取得
	 * @since	0.0.4
	 * @param dto		対象出勤簿DTO
	 * @return
	 * <p>
	 * 一次差戻ならtrue、そうでない場合false
	 * </p>
	 * @throws Exception
	 */
	public static boolean is1stReturned(KintaiCommonDtoInterface dto) throws Exception {
		if (VariousPart.chkExistObject(dto)) {
			return is1stReturned(dto.getSnRiyuu());
		}
		return false;
	}

	/**
	 * 出勤簿二次承認済フラグ取得
	 * @param dto		対象出勤簿DTO
	 * @return
	 * <p>
	 * 承認済ならtrue、そうでない場合false
	 * </p>
	 */
	public static boolean is2ndApproved(String snriyuu) {
		return VariousPart.getApprovalStatusCodeArray()[3].equals(snriyuu);
	}

	/**
	 * 出勤簿二次承認済フラグ取得
	 * @param dto		対象出勤簿DTO
	 * @return
	 * <p>
	 * 承認済ならtrue、そうでない場合false
	 * </p>
	 * @throws Exception
	 */
	public static boolean is2ndApproved(KintaiCommonDtoInterface dto) {
		if (VariousPart.chkExistObject(dto)) {
			return is2ndApproved(dto.getSnRiyuu());
		}
		return false;
	}

	/**
	 * 出勤簿二次承認済フラグ取得
	 * @since	0.0.4
	 * @param dto		対象出勤簿DTO
	 * @return
	 * <p>
	 * 二次差戻済ならtrue、そうでない場合false
	 * </p>
	 */
	public static boolean is2ndReturned(String snriyuu) {
		return VariousPart.getApprovalStatusCodeArray()[4].equals(snriyuu);
	}

	/**
	 * 出勤簿二次承認済フラグ取得
	 * @since	0.0.4
	 * @param dto		対象出勤簿DTO
	 * @return
	 * <p>
	 * 二次差戻済ならtrue、そうでない場合false
	 * </p>
	 * @throws Exception
	 */
	public static boolean is2ndReturned(KintaiCommonDtoInterface dto) {
		if (VariousPart.chkExistObject(dto)) {
			return is2ndReturned(dto.getSnRiyuu());
		}
		return false;
	}

	/**
	 * 出勤簿承認済フラグ取得
	 * @param dto		対象出勤簿DTO
	 * @return
	 * <p>
	 * 承認済ならtrue、そうでない場合false
	 * </p>
	 * @throws Exception
	 */
	public static boolean isApproved(KintaiCommonDtoInterface dto) throws Exception {
		if (VariousPart.chkExistObject(dto)) {
			if (is1stApproved(dto) || is2ndApproved(dto)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 利用可能勤怠承認ルート情報一覧
	 * @since	0.0.2
	 * @param kcode 対象社員コード
	 * @param targetDate	対象年月日
	 * @return 現状所属承認ユニットコードリスト
	 * @throws Exception
	 */
	public String[][] getBelongRouteInfoArray(String kCode, Date targetDate) throws Exception {
		// 情報の取得
		/*		
		List<AttendanceRouteDto> listRoute = getAttendanceRouteDao().findForAvailable(
				kcode,
				DatePart.convDateFormattedByHyphen(calculate().getStartDate(targetDate))
		);
		 */
		List<AttendanceRouteDto> listRoute = getAttendanceRouteList(kCode, targetDate);
		String[][] aryRoute = new String[listRoute.size()][5];
		for (int i = 0; i < aryRoute.length; i++) {
			aryRoute[i][0] = listRoute.get(i).getSCode();
			aryRoute[i][1] = listRoute.get(i).getKCode();
			aryRoute[i][2] = listRoute.get(i).getLayer1();
			aryRoute[i][3] = listRoute.get(i).getLastLayer();
			aryRoute[i][4] = listRoute.get(i).getJCode();
		}
		return aryRoute;
	}

	/**
	 * 利用可能勤怠承認ルート情報一覧
	 * @since	0.0.2
	 * @param kcode 対象社員コード
	 * @param targetDate	対象年月日
	 * @return 現状所属承認ユニットコードリスト
	 * <p>
	 * [0]…一次承認ルートコード
	 * [1]…二次承認ルートコード
	 * </p>
	 * @throws Exception
	 */
	public String[] getTargetRouteInfo(String kcode, Date targetDate) throws Exception {
		String[] aryRoute = new String[2];
		aryRoute[0] = "";
		aryRoute[1] = "";
		// 勤怠承認ルート取得
		String[][] aryRouteInfo = getBelongRouteInfoArray(
				human().getBasisInfoOfUser().getKCode(),
				targetDate
		);
		// 検索範囲取得
		int startDate = DatePart.convDateToInteger(calculate().getStartDate(targetDate));
		// 対象者社員コード
		String targetKCode = "";
		HumanBasisDtoInterface targetDto = human().getMKihonDao().findForApprovalKCode(
				kcode,
				human().getBasisInfoOfUser().getJCode(),
				user.getDataLevel(),
				startDate
		);
		if (VariousPart.chkExistObject(targetDto)) {
			targetKCode = targetDto.getKCode();
		} 
		for (int i = 0; i < aryRouteInfo.length; i++) {
			// 対象社員コード
			if (aryRouteInfo[i][1].equals(targetKCode)) {
				aryRoute[0] = aryRouteInfo[i][2];
				aryRoute[1] = aryRouteInfo[i][3];
				break;
			}
			// 選択所属から検索
			else if (aryRouteInfo[i][0].equals(section().getBelongSectionCode(targetKCode))) {
				aryRoute[0] = aryRouteInfo[i][2];
				aryRoute[1] = aryRouteInfo[i][3];
				break;		
			}
		}
		return aryRoute;
	}

	/**
	 * 承認理由配列取得
	 * @since	0.0.3
	 * @return	承認理由配列
	 * @throws Exception
	 */
	public String[][] getApprovalReasonArray() throws Exception {
		// 承認理由
		return mospcode().getMosPCodeArray(CommonConst.TID_APPROVAL_REASON);
	}

	/**
	 * 承認理由表示
	 * @since	0.0.3
	 * @param riyuu 承認理由
	 * @return	result
	 * @throws Exception 
	 */
	public String[] getApproval(String riyuu) throws Exception {
		String[][] aryApprovalReason = getApprovalReasonArray();
		String[] result = new String[2];
		for (int k = 0; k < aryApprovalReason.length; k++) {
			if (KintaiApprovalPart.isRequest(riyuu)) {
				// 申請中の場合（一次…申請中、二次…空欄）
				result[0] = aryApprovalReason[0][1];
				result[1] = "";
			} else if (KintaiApprovalPart.is1stApproved(riyuu)) {
				// 一次承認済の場合（一次…承認済、二次申請中）
				result[0] = aryApprovalReason[1][1];
				result[1] = aryApprovalReason[0][1];
			} else if (riyuu.equals(CommonConst.NUM_ATTENDANCE_1ST_RETURNED)) {
				// 一次差戻の場合（一次…差戻、二次…空欄）
				result[0] = aryApprovalReason[2][1];
				result[1] = "";
			} else if (KintaiApprovalPart.is2ndApproved(riyuu)) {
				// 二次承認済の場合（一次…承認済、二次承認済）
				result[0] = aryApprovalReason[1][1];
				result[1] = aryApprovalReason[3][1];
			} else if (riyuu.equals(CommonConst.NUM_ATTENDANCE_2ND_RETURNED)) {
				// 一次差戻の場合（一次…二次差戻、二次…空欄）
				result[0] = aryApprovalReason[4][1];
				result[1] = "";
			} else {
				result[0] = "";
				result[1] = "";
			}
		}
		return result;
	}

	/**
	 * 勤怠承認状況名称取得
	 * @since	0.0.3
	 * @param snRiyuu		勤怠承認状況コード
	 * @return				勤怠承認状況名称
	 * @throws Exception
	 */
	public String getApprovalName(String snRiyuu) throws Exception {
		return StringPart.getCodeName(snRiyuu, getApprovalReasonArray());
	}

	/**
	 * 勤怠承認状況名称取得
	 * @since	0.0.3
	 * @param dto		対象DTO
	 * @return			勤怠承認状況名称
	 * @throws Exception
	 */
	public String getApprovalName(KintaiCommonDtoInterface dto) throws Exception {
		return getApprovalName(dto.getSnRiyuu());
	}

	/**
	 * 承認対象者一覧
	 * @since	0.0.4
	 * @param targetDate
	 * @return
	 * @throws MospException
	 * @throws Exception
	 */
	public List<MKihonDto> getApprovalEmployeeList(String kCode, Date targetDate) throws MospException, Exception {
		// 情報の設定
		List<MKihonDto> listEmployee = new ArrayList<MKihonDto>();
		List<AttendanceRouteDto> listRoute = getAttendanceRouteList(kCode, targetDate);
		Set<String> employeeKCodeSet = new HashSet<String>();
		for (AttendanceRouteDto dto : listRoute) {
			// 対象所属社員一覧
			List<MKihonDto> selectSectionUserList = human().getMKihonDao().findForApproval(
					dto.getSCode(),
					office().getBelongOfficeCode(kCode),
					kCode,
					mospuser().getUserInfoForKCode(kCode).getDataLevel(),
					DatePart.convDateToInteger(calculate().getStartDate(targetDate))
			);
			for (MKihonDto mKihonDto : selectSectionUserList) {
				employeeKCodeSet.add(mKihonDto.getKCode());
			}
			// 追加社員情報
			MKihonDto addMKihonDto = human().getBasisInfo(dto.getKCode());
			if (VariousPart.chkExistDto(addMKihonDto)) {
				employeeKCodeSet.add(addMKihonDto.getKCode());
			}
		}
		// 社員情報を一覧へ追加
		for (String employeeKCode : employeeKCodeSet) {
			listEmployee.add(human().getBasisInfo(employeeKCode));
		}
		return listEmployee;
	}

	/**
	 * 対象勤怠承認ルート一覧リスト取得
	 * @since	0.0.5
	 * @param kCode			対象承認者社員コード
	 * @param targetDate	対象年月日
	 * @return list 検索結果(DTOのList)
	 * @throws MospException
	 * @throws Exception
	 */
	public List<AttendanceRouteDto> getAttendanceRouteList(
			String kCode,
			Date targetDate
	) throws MospException, Exception {
		return getAttendanceRouteDao().findForApproval(
				kCode,
				section().getBelongSectionCode(kCode),
				office().getBelongOfficeCode(kCode),
				DatePart.convDateFormattedByHyphen(calculate().getStartDate(targetDate))
		);
	}

	/**
	 * 対象社員勤怠承認ルートコード取得
	 * @since	0.0.5
	 * @param kCode		対象社員コード
	 * @return	勤怠承認ルートコード
	 * @throws Exception
	 */
	public String getRequestRouteCode(String kCode) throws Exception {
		PmAttendanceDto dto = getPmAttendanceDao().findForKCode(kCode);
		if (!VariousPart.chkExistDto(dto)) {
			dto = getPmAttendanceDao().findForRequest(
					section().getBelongSectionCode(kCode),
					office().getBelongOfficeCode(kCode)
			);
		}
		if (VariousPart.chkExistDto(dto)) {
			return dto.getRtCode();
		}
		return null;
	}

	/**
	 * 勤怠承認ワークフロー承認状況コード取得
	 * @since	0.0.6
	 * @param snriyuu	対象勤怠承認コード
	 * @return
	 */
	public static String[] toWorkflowStatus(String snriyuu) {
		String number = "";
		String status = "";
		if (isRequest(snriyuu)) {
			number = String.valueOf(CommonConst.NUM_REQUEST_LAYER);
			status = WorkflowPart.getStatusCodeArray()[0];
		}
		if (is1stApproved(snriyuu)) {
			number = String.valueOf(CommonConst.NUM_LAYER1);
			status = WorkflowPart.getStatusCodeArray()[1];
		}
		if (is1stReturned(snriyuu)) {
			number = String.valueOf(CommonConst.NUM_LAYER1);
			status = WorkflowPart.getStatusCodeArray()[2];
		}
		if (is2ndApproved(snriyuu)) {
			number = String.valueOf(CommonConst.NUM_LAST_LAYER);
			status = WorkflowPart.getStatusCodeArray()[1];
		}
		if (is2ndReturned(snriyuu)) {
			number = String.valueOf(CommonConst.NUM_LAST_LAYER);
			status = WorkflowPart.getStatusCodeArray()[2];
		}
		return new String[]{ number, status };
	}

}
