package jp.mosp.workflow.action;

import jp.mosp.common.CommonConst;
import jp.mosp.common.action.MosPWorkflowAction;
import jp.mosp.common.common.MospConst;
import jp.mosp.common.common.MospException;
import jp.mosp.common.common.MospUtility;
import jp.mosp.common.dto.CtWorkflowDto;
import jp.mosp.common.part.DatePart;
import jp.mosp.common.part.KintaiApprovalPart;
import jp.mosp.common.part.WorkflowPart;

import jp.mosp.human.dto.MKihonDto;

import jp.mosp.workflow.dto.CtOvertimeRequestDto;
import jp.mosp.workflow.vo.OverTimeApprovalCardVo;

public class OverTimeApprovalCardAction extends MosPWorkflowAction {

	// コマンド
	public  static final String CMD_CARD_SELECT 		= "K2136";
	private static final String CMD_CARD_APPROVED 	= "K2137";
	private static final String CMD_CARD_RETURNED 	= "K2138";

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

	public void action() throws Exception {
		// VO準備
		OverTimeApprovalCardVo vo = new OverTimeApprovalCardVo(cfg, msg, nam, cmd, aspUser, user);
		// VO及びフォワード先URLの設定
		setVo(vo);
		setUrl(vo.getRetUrl());
		// DTOの取得
		CtOvertimeRequestDto dto;
		Object obj = session.getAttribute(MospConst.ATT_DTO);
		dto = obj instanceof CtOvertimeRequestDto ? (CtOvertimeRequestDto)obj : null;
		// ユーザ情報の取得
		getInfo(user.getUserId());
		// コマンド毎の処理
		if (cmd.equals(CMD_CARD_SELECT)) {
			// 表示(キーで情報を検索)
			// データの取得
			dto = getOverTimeRequest(vo.getIntParam(key2));
			chkExist(dto);
			// VOに情報をセット
			vo.setFields(dto);
			// 承認状況の設定
			setApprovalStatus(vo, dto);
			// セッションにDTOをセット
			session.setAttribute(MospConst.ATT_DTO, dto);
		} else if (cmd.equals(CMD_CARD_APPROVED)) {
			// 承認
			approved(vo, dto);
			// 承認状況の設定
			setApprovalStatus(vo, dto);
			// セッションにDTOをセット
			session.setAttribute(MospConst.ATT_DTO, dto);
		} else if (cmd.equals(CMD_CARD_RETURNED)) {
			vo.setParams(request);
			// 差戻
			dto = returned(vo, dto);
			// 承認状況の設定
			setApprovalStatus(vo, dto);
			// セッションにDTOをセット
			session.setAttribute(MospConst.ATT_DTO, dto);
		} else {
			throw new MospException(MospConst.EX_CMD_INVALID);
		}
	}

	/**
	 * 承認処理
	 * @param vo			対象VO
	 * @param dto			対象DTO
	 * @throws Exception
	 */
	private void approved(OverTimeApprovalCardVo vo, CtOvertimeRequestDto dto) throws Exception {
		// 残業申請承認処理
		if (runOverTimeRequestApproved(dto, vo)) {
			// コミット
			commit();
			// メッセージの表示
			vo.setMessage(MospUtility.getMessage(msg, CommonConst.MSG_CODE_WORKFLOW_UPDATE, ""));
		}
	}

	/**
	 * 差戻処理
	 * @param vo		対象VO
	 * @param dto		対象DTO
	 * @return
	 * @throws Exception 
	 * @throws MospException 
	 */
	private CtOvertimeRequestDto returned(OverTimeApprovalCardVo vo, CtOvertimeRequestDto dto) throws MospException, Exception {
		// パラメータの妥当性確認
		vo.validate();
		// ワークフロー取得
		CtWorkflowDto workflowDto = workflowDao().findForUpdate(dto.getWorkflow());
		// 承認ルート取得
		String[] aryRouteInfo = getTargetRouteInfo(dto.getKCode(), dto.getWorkDate());
		// 差戻しフラグ
		boolean canReturn = false;
		// 一次差戻
		if (workflowDto.getLayerNumber() == CommonConst.NUM_REQUEST_LAYER) {
			if (isApprover(aryRouteInfo[0], dto.getWorkDate())) {
				if (isStatusRequest(dto.getWorkflow())) {
					workflowDto.setCurrentStatus(WorkflowPart.getStatusCodeArray()[2]);
					workflowDto.setLayerNumber(CommonConst.NUM_LAYER1);
					canReturn = true;
				}
			} else {
				StringBuffer sb = new StringBuffer();
				sb.append(DatePart.convDateToFormatDateJP(dto.getWorkDate()));
				sb.append(CommonConst.STR_UNDER_SEPARATOR);
				sb.append(CommonConst.NAM_OVER_TIME_REQUEST);
				vo.addErrMessage(MospUtility.getMessage(
						msg,
						CommonConst.MSG_CODE_DENY_APPROVAL,
						sb.toString())
				);
			}
		} 
		// 二次差戻
		else if (workflowDto.getLayerNumber() == CommonConst.NUM_LAYER1) {
			if (isApprover(aryRouteInfo[1], dto.getWorkDate())) {
				if (isStatusApproved(dto.getWorkflow())) {
					workflowDto.setCurrentStatus(WorkflowPart.getStatusCodeArray()[2]);
					workflowDto.setLayerNumber(CommonConst.NUM_LAST_LAYER);
					canReturn = true;
				}
			} else {
				StringBuffer sb = new StringBuffer();
				sb.append(DatePart.convDateToFormatDateJP(dto.getWorkDate()));
				sb.append(CommonConst.STR_UNDER_SEPARATOR);
				sb.append(CommonConst.NAM_OVER_TIME_REQUEST);
				vo.addErrMessage(MospUtility.getMessage(
						msg,
						CommonConst.MSG_CODE_DENY_APPROVAL,
						sb.toString())
				);
			}
		} else {
			if (isStatusApproved(dto.getWorkflow())) {
				StringBuffer sb = new StringBuffer();
				sb.append(DatePart.convDateToFormatDateJP(dto.getWorkDate()));
				sb.append(CommonConst.MSG_OF);
				sb.append(CommonConst.NAM_OVER_TIME_REQUEST);
				// エラーメッセージ
				vo.addErrMessage(MospUtility.getMessage(msg, 
						CommonConst.MSG_CODE_SELECT_ALREADY_APPROVED,
						sb.toString())
				);
			}
		}
		// 差戻し中の場合
		if (isStatusReturned(dto.getWorkflow())) {
			StringBuffer sb = new StringBuffer();
			sb.append(DatePart.convDateToFormatDateJP(dto.getWorkDate()));
			sb.append(CommonConst.MSG_OF);
			sb.append(CommonConst.NAM_OVER_TIME_REQUEST);
			// エラーメッセージ
			vo.addErrMessage(MospUtility.getMessage(msg, 
					CommonConst.MSG_CODE_SELECT_ALREADY_RETURNED,
					sb.toString())
			);
		}
		if (canReturn) {
			// ワークフローの更新
			workflowDao().update(workflowDto);
			chkUpdate(workflowDao().findForKey(workflowDto.getWorkflow()));
			// 差戻しコメントの登録
			registComment(workflowDto.getWorkflow(), mKihon.getKCode(), dto.getKCode(), vo.getTxtComment());
			// コミット
			commit();
			// メッセージの表示
			vo.setMessage(MospUtility.getMessage(msg, CommonConst.MSG_CODE_WORKFLOW_UPDATE, ""));
		}
		return dto;
	}

	/**
	 * 承認状況情報の設定
	 * @param vo			対象VO
	 * @param dto			対象DTO
	 * @throws Exception
	 */
	private void setApprovalStatus(
			OverTimeApprovalCardVo vo,
			CtOvertimeRequestDto dto
	) throws Exception {
		MKihonDto mKihonDto = getBasisInfo(dto.getKCode());
		vo.setLblKCode(mKihonDto.getKCode());
		vo.setLblKName(mKihonDto.getSimei());
		vo.setLblSectionName(getSectionName(mKihonDto.getSCode()));
		String statusCode = toKintaiApprovalStatus(dto.getWorkflow());
		vo.setLblApprovalStatus(getApprovalName(statusCode));
		// モード設定
		if (KintaiApprovalPart.is1stApproved(statusCode)) {
			vo.setMode(OverTimeApprovalCardVo.MODE_APPROVED);
		} else if (KintaiApprovalPart.is1stReturned(statusCode)
				|| KintaiApprovalPart.is2ndApproved(statusCode)
				|| KintaiApprovalPart.is2ndReturned(statusCode)
		) {
			vo.setMode(OverTimeApprovalCardVo.MODE_VIEW);
		}
		// 差戻しコメント一覧
		setReturnedComment(vo, dto.getKCode(), dto.getWorkflow());
	}

}
