/*
 * 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.kintai.common.part;

import java.util.ArrayList;
import java.util.List;

import jp.mosp.common.CommonConst;
import jp.mosp.common.part.PartInfo;
import jp.mosp.common.utils.VariousUtil;
import jp.mosp.kintai.common.dao.CtWorkflowCommentDao;
import jp.mosp.kintai.common.dao.CtWorkflowDao;
import jp.mosp.kintai.common.dto.CtWorkflowCommentDto;
import jp.mosp.kintai.common.dto.CtWorkflowDto;

/**
 * ワークフローに関するPartクラス
 * @author yoshida
 *	@version	0.0.7
 */
public class WorkflowPart extends KintaiBasePart {
	
	/**
	 * コンストラクタ
	 */
	public WorkflowPart() {
		super();
	}
	
	/**
	 * コンストラクタ
	 * @param partInfo Partを利用する際に必要な情報
	 */
	public WorkflowPart(PartInfo partInfo) {
		super(partInfo);
	}
	

	/**
	 * CtWorkflowDaoインスタンス
	 */
	private CtWorkflowDao	workflowDao;
	

	/**
	 * ワークフローテーブルDAOの取得
	 * @return	初期化済みCtWorkflowDaoインスタンス
	 * @throws Exception	例外処理が発生した場合
	 */
	public CtWorkflowDao getCtWorkflowDao() throws Exception {
		if (VariousUtil.isNull(workflowDao)) {
			workflowDao = (CtWorkflowDao)getPreparedDao(CtWorkflowDao.class.getCanonicalName());
		}
		return workflowDao;
	}
	

	/**
	 * CtWorkflowCommentDaoインスタンス
	 */
	private CtWorkflowCommentDao	commentDao;
	

	/**
	 * ワークフローコメントテーブル用DAOの取得
	 * @since	0.0.2
	 * @return	初期化済みCtWorkflowCommentDaoインスタンス
	 * @throws Exception	例外処理が発生した場合
	 */
	public CtWorkflowCommentDao getCtWorkflowCommentDao() throws Exception {
		if (VariousUtil.isNull(commentDao)) {
			commentDao = (CtWorkflowCommentDao)getPreparedDao(CtWorkflowCommentDao.class.getCanonicalName());
		}
		return commentDao;
	}
	
	/**
	 * ステータスコードリスト取得
	 * @return ステータスコードリスト配列
	 * <p>
	 * [0]…未承認（申請中）
	 * [1]…承認済
	 * [2]…差戻中
	 * [3]…承認解除
	 * [4]…下書き
	 * </p>
	 */
	public static String[] getStatusCodeArray() {
		// 配列の作成
		String[] aryStatus = new String[5];
		aryStatus[0] = CommonConst.CODE_REQUEST;
		aryStatus[1] = CommonConst.CODE_APPROVED;
		aryStatus[2] = CommonConst.CODE_RETURNED;
		aryStatus[3] = CommonConst.CODE_UNLOCK;
		aryStatus[4] = CommonConst.CODE_DRAFT;
		return aryStatus;
	}
	
	/**
	 * ステータスリスト取得
	 * @return ステータスリスト配列
	 * <p>
	 * [0]…未承認（申請中）
	 * [1]…承認済
	 * [2]…差戻中
	 * [3]…承認解除
	 * [4]…下書き
	 * </p>
	 */
	public static String[][] getStatusArray() {
		// 配列の作成
		String[][] aryStatus = new String[5][2];
		aryStatus[0][0] = getStatusCodeArray()[0];
		aryStatus[0][1] = CommonConst.NAM_REMAIN_APPROVED;
		aryStatus[1][0] = getStatusCodeArray()[1];
		aryStatus[1][1] = CommonConst.NAME_APPROVED;
		aryStatus[2][0] = getStatusCodeArray()[2];
		aryStatus[2][1] = CommonConst.NAME_RETURNED;
		aryStatus[3][0] = getStatusCodeArray()[3];
		aryStatus[3][1] = CommonConst.NAME_UNLOCK;
		aryStatus[4][0] = getStatusCodeArray()[4];
		aryStatus[4][1] = CommonConst.NAME_DRAFT;
		return aryStatus;
	}
	
	/**
	 * ワークフロー取得
	 * @param workflow		ワークフロー番号
	 * @return	検索結果(DTO)
	 * @throws Exception	例外処理が発生した場合
	 */
	public CtWorkflowDto getWorkflowDto(long workflow) throws Exception {
		return getCtWorkflowDao().findForKey(workflow);
	}
	
	/**
	 * 承認状況コード取得
	 * @param workflow		対象ワークフロー番号
	 * @return	承認状況コード
	 * @throws Exception 	例外処理が発生した場合
	 */
	public String getStatusCode(long workflow) throws Exception {
		return getStatusCode(getWorkflowDto(workflow));
	}
	
	/**
	 * 承認状況コード取得
	 * @since	0.0.7
	 * @param dto	対象DTO
	 * @return	承認状況コード
	 */
	public static String getStatusCode(CtWorkflowDto dto) {
		if (VariousUtil.isNotNull(dto)) {
			return dto.getCurrentStatus();
		}
		return "";
	}
	
	/**
	 * 未承認状況の確認
	 * @since	0.0.4
	 * @param code		対象コード
	 * @return	未承認状況の是非
	 */
	public static boolean isRequest(String code) {
		return getStatusCodeArray()[0].equals(code);
	}
	
	/**
	 * 未承認状況の確認
	 * @since	0.0.7
	 * @param dto	対象DTO
	 * @return	未承認状況の是非
	 */
	public static boolean isStatusRequest(CtWorkflowDto dto) {
		return isRequest(getStatusCode(dto));
	}
	
	/**
	 * 未承認状況の確認
	 * @param workflow		対象ワークフロー番号
	 * @return	未承認状況の是非
	 * @throws Exception 	例外処理が発生した場合
	 */
	public boolean isStatusRequest(long workflow) throws Exception {
		return isRequest(getStatusCode(workflow));
	}
	
	/**
	 * 承認済み状況の確認
	 * @since	0.0.4
	 * @param code		対象コード
	 * @return	承認済み状況の是非
	 */
	public static boolean isApproved(String code) {
		return getStatusCodeArray()[1].equals(code);
	}
	
	/**
	 * 承認済み状況の確認
	 * @since	0.0.7
	 * @param dto	対象DTO
	 * @return	承認済み状況の是非
	 */
	public static boolean isStatusApproved(CtWorkflowDto dto) {
		return isApproved(getStatusCode(dto));
	}
	
	/**
	 * 承認済み状況の確認
	 * @param workflow		対象ワークフロー番号
	 * @return	承認済み状況の是非
	 * @throws Exception 	例外処理が発生した場合
	 */
	public boolean isStatusApproved(long workflow) throws Exception {
		return isApproved(getStatusCode(workflow));
	}
	
	/**
	 * 差戻状況の確認
	 * @since	0.0.4
	 * @param code		対象コード
	 * @return	差戻状況の是非
	 */
	public static boolean isReturned(String code) {
		return getStatusCodeArray()[2].equals(code);
	}
	
	/**
	 * 差戻状況の確認
	 * @param workflow 	ワークフロー番号
	 * @return	差戻状況の是非
	 * @throws Exception 	例外処理が発生した場合
	 */
	public boolean isStatusReturned(long workflow) throws Exception {
		return isReturned(getStatusCode(workflow));
	}
	
	/**
	 * 差戻状況の確認
	 * @since	0.0.7
	 * @param dto 	対象DTO
	 * @return	差戻状況の是非
	 */
	public static boolean isStatusReturned(CtWorkflowDto dto) {
		return isReturned(getStatusCode(dto));
	}
	
	/**
	 * 下書き判断
	 * @since	0.0.3
	 * @param code		対象コード
	 * @return	下書き状況の是非
	 */
	public static boolean isDraft(String code) {
		return getStatusCodeArray()[4].equals(code);
	}
	
	/**
	 * 下書き状況の確認
	 * @since	0.0.3
	 * @param workflow		対象ワークフロー番号
	 * @return	下書き状況の是非
	 * @throws Exception 	例外処理が発生した場合
	 */
	public boolean isStatusDraft(long workflow) throws Exception {
		return isDraft(getStatusCode(workflow));
	}
	
	/**
	 * 下書き状況の確認
	 * @since	0.0.7
	 * @param dto	対象DTO
	 * @return	下書き状況の是非
	 */
	public static boolean isStatusDraft(CtWorkflowDto dto) {
		return isDraft(getStatusCode(dto));
	}
	
	/**
	 * 承認者向けコメント取得
	 * @since	0.0.2
	 * @param workflow		対象ワークフロー番号
	 * @return				最新のコメント
	 * @throws Exception	例外処理が発生した場合
	 */
	public CtWorkflowCommentDto getWorkflowCommentForApprover(long workflow) throws Exception {
		CtWorkflowCommentDto dto = new CtWorkflowCommentDto();
		CtWorkflowDto workflowDto = getWorkflowDto(workflow);
		if (VariousUtil.chkExistDto(workflowDto)) {
			dto = getCtWorkflowCommentDao().findForMaxApprover(workflowDto.getRtCode(), workflow);
		}
		return dto;
	}
	
	/**
	 * 対象者向けコメント取得
	 * @since	0.0.2
	 * @param target		コメント対象社員コード	
	 * @param workflow		対象ワークフロー番号
	 * @return				最新のコメント
	 * @throws Exception	例外処理が発生した場合
	 */
	public CtWorkflowCommentDto getWorkflowCommentForTarget(String target, long workflow) throws Exception {
		CtWorkflowCommentDto dto = new CtWorkflowCommentDto();
		if (VariousUtil.chkExistDto(getWorkflowDto(workflow))) {
			dto = getCtWorkflowCommentDao().findForMaxTarget(target, workflow);
		}
		return dto;
	}
	
	/**
	 * 対象者向けコメント一覧
	 * @since	0.0.2
	 * @param target		コメント対象社員コード	
	 * @param workflow		対象ワークフロー番号
	 * @return	コメント一覧	最新のコメントから順に整列
	 * @throws Exception	例外処理が発生した場合
	 */
	public List<CtWorkflowCommentDto> getWorkflowCommentListForTarget(String target, long workflow) throws Exception {
		List<CtWorkflowCommentDto> listComment = new ArrayList<CtWorkflowCommentDto>();
		if (VariousUtil.chkExistDto(getWorkflowDto(workflow))) {
			listComment = getCtWorkflowCommentDao().findForTarget(target, workflow);
		}
		return listComment;
	}
	
	/**
	 * コメント一覧配列
	 * @since	0.0.2
	 * @param target		コメント対象社員コード	
	 * @param workflow		対象ワークフロー番号
	 * @return				コメント一覧配列
	 * @throws Exception	例外処理が発生した場合
	 */
	public String[][] getWorkflowCommentArray(String target, long workflow) throws Exception {
		List<CtWorkflowCommentDto> list = getWorkflowCommentListForTarget(target, workflow);
		String[][] aryComments = new String[list.size()][2];
		for (int i = 0; i < aryComments.length; i++) {
			CtWorkflowCommentDto dto = list.get(i);
			aryComments[i][0] = part().human().getKName(dto.getKCode());
			aryComments[i][1] = dto.getAuthorComment();
		}
		return aryComments;
	}
	
	/**
	 * 勤怠承認ステータスコード取得
	 * @since	0.0.3
	 * @param workflow			対象ワークフロー番号
	 * @return	勤怠承認ステータスコード
	 * @throws Exception	例外処理が発生した場合
	 */
	public String toKintaiApprovalStatus(long workflow) throws Exception {
		String status = "";
		CtWorkflowDto dto = getWorkflowDto(workflow);
		if (isStatusDraft(dto)) {
			// 下書き
			status = getStatusCodeArray()[4];
		} else if (isStatusRequest(dto)) {
			// 未承認（申請中）
			status = VariousUtil.getApprovalStatusCodeArray()[0];
		} else if (isStatus1stApproved(dto)) {
			// 一次承認
			status = VariousUtil.getApprovalStatusCodeArray()[1];
		} else if (isStatus1stReturned(dto)) {
			// 一次差戻
			status = VariousUtil.getApprovalStatusCodeArray()[2];
		} else if (isStatusLastApproved(dto)) {
			// 二次承認
			status = VariousUtil.getApprovalStatusCodeArray()[3];
		} else if (isStatusLastReturned(dto)) {
			// 二次差戻
			status = VariousUtil.getApprovalStatusCodeArray()[4];
		}
		return status;
	}
	
	/**
	 * 承認階層取得
	 * @since	0.0.5
	 * @param workflow		対象ワークフロー番号
	 * @return	承認階層
	 * @throws Exception	例外処理が発生した場合
	 */
	public int getWorkflowLayer(long workflow) throws Exception {
		return getWorkflowLayer(getWorkflowDto(workflow));
	}
	
	/**
	 * 承認階層取得
	 * @since	0.0.7
	 * @param dto	対象DTO
	 * @return	承認階層
	 */
	public static int getWorkflowLayer(CtWorkflowDto dto) {
		if (VariousUtil.isNotNull(dto)) {
			return dto.getLayerNumber();
		}
		return 0;
	}
	
	/**
	 * 承認階層を一段階上げ、承認済みへ変更
	 * @since	0.0.6
	 * @param dto	対象DTO
	 */
	public static void shiftApproved(CtWorkflowDto dto) {
		dto.setCurrentStatus(WorkflowPart.getStatusCodeArray()[1]);
		int layer = dto.getLayerNumber();
		if (!isLastLayer(dto)) {
			layer++;
			dto.setLayerNumber(layer);
		}
	}
	
	/**
	 * 最終承認済みへ変更
	 * @since	0.0.6
	 * @param dto	対象DTO
	 */
	public static void shiftLastApproved(CtWorkflowDto dto) {
		dto.setCurrentStatus(WorkflowPart.getStatusCodeArray()[1]);
		dto.setLayerNumber(CommonConst.NUM_LAST_LAYER);
	}
	
	/**
	 * 承認階層を一段階上げ、承認済みへ変更
	 * @since	0.0.6
	 * @param dto	対象DTO
	 */
	public static void shiftReturned(CtWorkflowDto dto) {
		dto.setCurrentStatus(WorkflowPart.getStatusCodeArray()[2]);
		int layer = dto.getLayerNumber();
		if (!isLastLayer(dto)) {
			layer++;
			dto.setLayerNumber(layer);
		}
	}
	
	/**
	 * 最終差戻へ変更
	 * @since	0.0.6
	 * @param dto	対象DTO
	 */
	public static void shiftLastReturned(CtWorkflowDto dto) {
		dto.setCurrentStatus(WorkflowPart.getStatusCodeArray()[2]);
		dto.setLayerNumber(CommonConst.NUM_LAST_LAYER);
	}
	
	/**
	 * 一次承認判断
	 * @since	0.0.7
	 * @param dto	対象DTO
	 * @return	一次承認の場合true、そうでないfalse
	 */
	public static boolean isStatus1stApproved(CtWorkflowDto dto) {
		if (isStatusApproved(dto)) {
			return is1stLayer(dto);
		}
		return false;
	}
	
	/**
	 * 一次承認判断
	 * @since	0.0.7
	 * @param workflow 	ワークフロー番号
	 * @return	一次承認の場合true、そうでないfalse
	 * @throws Exception	例外処理が発生した場合
	 */
	public boolean isStatus1stApproved(long workflow) throws Exception {
		return isStatus1stApproved(getWorkflowDto(workflow));
	}
	
	/**
	 * 一次差戻判断
	 * @since	0.0.7
	 * @param dto	対象DTO
	 * @return	一次差戻の場合true、そうでないfalse
	 */
	public static boolean isStatus1stReturned(CtWorkflowDto dto) {
		if (isStatusReturned(dto)) {
			return is1stLayer(dto);
		}
		return false;
	}
	
	/**
	 * 一次差戻判断
	 * @since	0.0.7
	 * @param workflow 	ワークフロー番号
	 * @return	一次差戻の場合true、そうでないfalse
	 * @throws Exception	例外処理が発生した場合
	 */
	public boolean isStatus1stReturned(long workflow) throws Exception {
		return isStatus1stReturned(getWorkflowDto(workflow));
	}
	
	/**
	 * 最終承認判断
	 * @since	0.0.7
	 * @param dto	対象DTO
	 * @return	最終承認の場合true、そうでないfalse
	 */
	public static boolean isStatusLastApproved(CtWorkflowDto dto) {
		if (isStatusApproved(dto)) {
			return isLastLayer(dto);
		}
		return false;
	}
	
	/**
	 * 最終承認判断
	 * @since	0.0.7
	 * @param workflow 	ワークフロー番号
	 * @return	最終承認の場合true、そうでないfalse
	 * @throws Exception	例外処理が発生した場合
	 */
	public boolean isStatusLastApproved(long workflow) throws Exception {
		return isStatusLastApproved(getWorkflowDto(workflow));
	}
	
	/**
	 * 最終差戻判断
	 * @since	0.0.7
	 * @param dto	対象DTO
	 * @return	最終差戻の場合true、そうでないfalse
	 */
	public static boolean isStatusLastReturned(CtWorkflowDto dto) {
		if (isStatusReturned(dto)) {
			return isLastLayer(dto);
		}
		return false;
	}
	
	/**
	 * 最終差戻判断
	 * @since	0.0.7
	 * @param workflow 	ワークフロー番号
	 * @return	最終差戻の場合true、そうでないfalse
	 * @throws Exception	例外処理が発生した場合
	 */
	public boolean isStatusLastReturned(long workflow) throws Exception {
		return isStatusLastReturned(getWorkflowDto(workflow));
	}
	
	/**
	 * 申請中承認階層判断
	 * @since	0.0.7
	 * @param dto	対象DTO
	 * @return	申請中承認階層の場合true、そうでない場合false
	 */
	public static boolean isRequestLayer(CtWorkflowDto dto) {
		return CommonConst.NUM_REQUEST_LAYER == getWorkflowLayer(dto);
	}
	
	/**
	 * 一次承認階層判断
	 * @since	0.0.7
	 * @param dto	対象DTO
	 * @return	一次承認階層の場合true、そうでない場合false
	 */
	public static boolean is1stLayer(CtWorkflowDto dto) {
		return CommonConst.NUM_LAYER1 == getWorkflowLayer(dto);
	}
	
	/**
	 * 最終承認階層判断
	 * @since	0.0.7
	 * @param dto	対象DTO
	 * @return	最終承認階層の場合true、そうでない場合false
	 */
	public static boolean isLastLayer(CtWorkflowDto dto) {
		return CommonConst.NUM_LAST_LAYER == getWorkflowLayer(dto);
	}
	
}
