/*
 * 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.setup.action;

import java.util.Date;
import java.util.Map.Entry;

import jp.mosp.framework.base.MospException;
import jp.mosp.framework.base.MospUser;
import jp.mosp.framework.constant.MospConst;
import jp.mosp.framework.property.RoleProperty;
import jp.mosp.framework.utils.SeUtility;
import jp.mosp.platform.base.PlatformAction;
import jp.mosp.platform.bean.human.EntranceRegistBeanInterface;
import jp.mosp.platform.bean.human.HumanRegistBeanInterface;
import jp.mosp.platform.bean.system.UserMasterRegistBeanInterface;
import jp.mosp.platform.bean.system.UserPasswordRegistBeanInterface;
import jp.mosp.platform.constant.PlatformConst;
import jp.mosp.platform.dto.human.EntranceDtoInterface;
import jp.mosp.platform.dto.human.HumanDtoInterface;
import jp.mosp.platform.dto.system.UserMasterDtoInterface;
import jp.mosp.platform.dto.system.UserPasswordDtoInterface;
import jp.mosp.platform.portal.action.IndexAction;
import jp.mosp.setup.vo.DbCreateVo;
import jp.mosp.setup.vo.FirstUserVo;

/**
 * 最初のユーザの新規登録を行う。<br>
 * 社員コード・有効日・姓名・姓名カナ・ログインユーザ名・入社日。<br>
 * 初ログインはこのログインユーザを使う。<br>
 * パスワードはログインユーザと同一。<br>
 * ログインするとパスワード変更画面へ遷移。<br>
 * ログインユーザは後に変更可。<br>
 */

public class FirstUserAction extends PlatformAction {
	
	/**
	 *  表示コマンド。<br>
	 *  初期表示を行う。<br>
	 */
	public static final String	CMD_SHOW	= "SU3000";
	
	/**
	 *  登録コマンド。<br>
	 *  新規ユーザを登録する。<br>
	 */
	public static final String	CMD_REGIST	= "SU3001";
	

	@Override
	public void action() throws MospException {
		// コマンド毎の処理
		if (mospParams.getCommand().equals(CMD_SHOW)) {
			// 表示
			prepareVo(false, false);
			show();
		} else if (mospParams.getCommand().equals(CMD_REGIST)) {
			// 新規登録
			prepareVo();
			insert();
		} else {
			throwInvalidCommandException();
		}
	}
	
	/**
	 * 初期表示処理を行う。<br>
	 * 有効日をリアルタイムにあらかじめ表示する。<br>
	 * @throws MospException 表示できなかった場合
	 */
	protected void show() throws MospException {
		// DB接続画面VO存在確認
		if (hasDbConfirmVo() == false) {
			// 繋がったらMosPへ
			mospParams.setNextCommand(IndexAction.CMD_SHOW);
			return;
		}
		// VO取得
		FirstUserVo vo = (FirstUserVo)mospParams.getVo();
		// システム日付取得
		Date date = getSystemDate();
		// 有効日設定
		vo.setTxtActivateYear(getStringYear(date));
		vo.setTxtActivateMonth(getStringMonth(date));
		vo.setTxtActivateDay(getStringDay(date));
		// 有効日モード設定
		vo.setModeActivateDate(PlatformConst.MODE_ACTIVATE_DATE_CHANGING);
	}
	
	/**
	 * 新規登録処理を行う。<br>
	 * 新規ユーザを登録する。<br>
	 * 自動的にユーザマスタで登録する。<br>
	 * @throws MospException 登録できなかった場合
	 */
	protected void insert() throws MospException {
		// DB接続画面VO存在確認
		if (hasDbConfirmVo() == false) {
			// 繋がったらMosPへ
			mospParams.setNextCommand(IndexAction.CMD_SHOW);
			return;
		}
		// VO取得
		FirstUserVo vo = (FirstUserVo)mospParams.getVo();
		// ログインしてる事とする（Insert_user）
		setInsertUser();
		// 人事マスタ登録
		registHuman();
		// 登録結果確認
		if (mospParams.hasErrorMessage()) {
			// 登録失敗メッセージ設定
			addInsertFailedMessage();
			// ログインしてる事とする（Insert_user）を削除
			deletInsertUser();
			return;
		}
		// 入社情報登録
		registEntrance();
		if (mospParams.hasErrorMessage()) {
			// 登録失敗メッセージ設定
			addInsertFailedMessage();
			// ログインしてる事とする（Insert_user）を削除
			deletInsertUser();
			return;
		}
		// ユーザマスタ登録
		registUser();
		if (mospParams.hasErrorMessage()) {
			// 登録失敗メッセージ設定
			addInsertFailedMessage();
			// ログインしてる事とする（Insert_user）を削除
			deletInsertUser();
			return;
		}
		// コミット
		commit();
		// ログインしてる事とする（Insert_user）を削除
		deletInsertUser();
		// 登録成功メッセージ設定
		addInsertNewMessage();
		// 人事情報一覧遷移用社員コード及び有効日設定
		vo.setTxtEmployeeCode(vo.getTxtEmployeeCode());
		vo.setModeActivateDate(getStringDate(getEditActivateDate()));
		// 次画面へ
		mospParams.setNextCommand(SetupFinishAction.CMD_SHOW);
	}
	
	/**
	 * セキュリティチェックを行う。<br>
	 * この画面から登録だけしていないかなどを確認する。<br>
	 * DB接続画面のVOが存在しているか確認する。<br>
	 * @return (true：存在する、false：存在しない)
	 */
	public boolean hasDbConfirmVo() {
		// DB作成画面のVOを呼び出す
		return mospParams.getStoredVo(DbCreateVo.class.getName()) != null;
	}
	
	/**
	 * VO(編集項目)の値をDTO(人事マスタ)に設定する。<br>
	 * @param dto 対象DTO
	 * @throws MospException 日付の取得に失敗した場合
	 */
	protected void setDtoFields(HumanDtoInterface dto) throws MospException {
		// VO準備
		FirstUserVo vo = (FirstUserVo)mospParams.getVo();
		// VOの値をDTOに設定
		dto.setActivateDate(getEditActivateDate());
		dto.setEmployeeCode(vo.getTxtEmployeeCode());
		dto.setLastName(vo.getTxtLastName());
		dto.setFirstName(vo.getTxtFirstName());
		dto.setLastKana(vo.getTxtLastKana());
		dto.setFirstKana(vo.getTxtFirstKana());
		dto.setWorkPlaceCode("");
		dto.setEmploymentContractCode("");
		dto.setSectionCode("");
		dto.setPositionCode("");
		// メールアドレスは未使用
		dto.setMail("");
	}
	
	/**
	 * insert_userに値を入れてあげる。<br>
	 * @throws MospException インスタンスの取得、或いはSQL実行に失敗した場合
	 */
	protected void setInsertUser() throws MospException {
		// VO準備
		FirstUserVo vo = (FirstUserVo)mospParams.getVo();
		MospUser mospUser = new MospUser();
		mospParams.setUser(mospUser);
		mospUser.setUserId(vo.getTxtUserId());
	}
	
	/**
	 * insert_userの値を消去。<br>
	 * セキュリティ上、消去してしまう。<br>
	 */
	protected void deletInsertUser() {
		// 消去
		mospParams.setUser(null);
	}
	
	/**
	 * VO(編集項目)の値をDTO(人事入社情報)に設定する。<br>
	 * @param dto 対象DTO
	 * @throws MospException インスタンスの取得、或いはSQL実行に失敗した場合
	 */
	protected void setDtoFields(EntranceDtoInterface dto) throws MospException {
		// VO準備
		FirstUserVo vo = (FirstUserVo)mospParams.getVo();
		// VOの値をDTOに設定
		dto.setEntranceDate(getEntranceDate());
		// 社員コードから個人IDを取得して設定
		dto.setPersonalId(reference().human().getPersonalId(vo.getTxtEmployeeCode(), getEditActivateDate()));
	}
	
	/**
	 * VO(編集項目)の値をDTO(ユーザマスタ)に設定する。<br>
	 * @param dto 対象DTO
	 * @throws MospException 人事情報の取得に失敗した場合
	 */
	protected void setDtoFields(UserMasterDtoInterface dto) throws MospException {
		// VO準備
		FirstUserVo vo = (FirstUserVo)mospParams.getVo();
		// VOの値をDTOに設定
		dto.setUserId(vo.getTxtUserId());
		dto.setActivateDate(getEditActivateDate());
		// 社員コードから個人IDを取得して設定
		dto.setPersonalId(reference().human().getPersonalId(vo.getTxtEmployeeCode(), getEditActivateDate()));
		// デフォルトロールコード設定
		dto.setRoleCode(getDefaultRole());
		// 無効フラグ設定(有効)
		dto.setInactivateFlag(MospConst.DELETE_FLAG_OFF);
	}
	
	/**
	 * VO(編集項目)の値をDTO(ユーザパスワード情報)に設定する。<br>
	 * @param dto 対象DTO
	 * @throws MospException インスタンスの取得、或いはSQL実行に失敗した場合
	 */
	protected void setDtoFields(UserPasswordDtoInterface dto) throws MospException {
		// VO準備
		FirstUserVo vo = (FirstUserVo)mospParams.getVo();
		// VOの値をDTOに設定
		dto.setChangeDate(getEditActivateDate());
		// ユーザID設定
		dto.setUserId(vo.getTxtUserId());
		// 初期パスワード取得
		String initialPassword = platform().passwordCheck().getInitialPassword(vo.getTxtUserId());
		// パスワード設定
		dto.setPassword(SeUtility.encrypt(SeUtility.encrypt(initialPassword)));
	}
	
	/**
	 * 人事マスタを登録する。<br>
	 * @throws MospException インスタンスの取得、或いはSQL実行に失敗した場合
	 */
	protected void registHuman() throws MospException {
		// 登録クラス取得		
		HumanRegistBeanInterface regist = platform().humanRegist();
		// DTOの準備
		HumanDtoInterface dto = regist.getInitDto();
		// DTOに値を設定
		setDtoFields(dto);
		// 登録処理
		regist.insert(dto);
	}
	
	/**
	 * 人事入社情報を登録する。<br>
	 * @throws MospException インスタンスの取得、或いはSQL実行に失敗した場合
	 */
	protected void registEntrance() throws MospException {
		// 入社日確認
		if (getEntranceDate() == null) {
			return;
		}
		// 入社情報登録クラス取得
		EntranceRegistBeanInterface regist = platform().entranceRegist();
		// 入社情報DTOの準備
		EntranceDtoInterface dto = regist.getInitDto();
		// 入社情報DTOに値を設定
		setDtoFields(dto);
		// 入社情報登録処理
		regist.insert(dto);
	}
	
	/**
	 * ユーザマスタを登録する。<br>
	 * @throws MospException インスタンスの取得、或いはSQL実行に失敗した場合
	 */
	protected void registUser() throws MospException {
		// VO取得
		FirstUserVo vo = (FirstUserVo)mospParams.getVo();
		// ユーザID確認
		if (vo.getTxtUserId().isEmpty()) {
			return;
		}
		// ユーザマスタ登録クラス取得
		UserMasterRegistBeanInterface regist = platform().userMasterRegist();
		// ユーザマスタDTOの準備
		UserMasterDtoInterface dto = regist.getInitDto();
		// ユーザマスタDTOに値を設定
		setDtoFields(dto);
		// ユーザマスタ登録処理
		regist.insert(dto);
		// ユーザパスワード情報
		registUserPassword();
	}
	
	/**
	 * ユーザパスワード情報を登録する。<br>
	 * @throws MospException インスタンスの取得、或いはSQL実行に失敗した場合
	 */
	protected void registUserPassword() throws MospException {
		// ユーザパスワード情報登録クラス取得
		UserPasswordRegistBeanInterface regist = platform().userPasswordRegist();
		// ユーザパスワード情報DTOの準備
		UserPasswordDtoInterface dto = regist.getInitDto();
		// ユーザパスワード情報DTOに値を設定
		setDtoFields(dto);
		// ユーザパスワード情報登録処理
		regist.regist(dto);
	}
	
	/**
	 * VOから有効日(編集)を取得する。<br>
	 * @return 有効日(編集)
	 */
	public Date getEditActivateDate() {
		// VO取得
		FirstUserVo vo = (FirstUserVo)mospParams.getVo();
		// 有効日取得
		return getDate(vo.getTxtActivateYear(), vo.getTxtActivateMonth(), vo.getTxtActivateDay());
	}
	
	/**
	 * VOから入社日を取得する。<br>
	 * @return 入社日
	 */
	protected Date getEntranceDate() {
		// VO取得
		FirstUserVo vo = (FirstUserVo)mospParams.getVo();
		// 入社日取得
		return getDate(vo.getTxtEntranceYear(), vo.getTxtEntranceMonth(), vo.getTxtEntranceDay());
	}
	
	/**
	 * デフォルトロールコードを取得する。<br>
	 * スーパユーザに設定
	 * @return デフォルトロールコード
	 */
	protected String getDefaultRole() {
		String roleCode = "";
		// ロール情報取得
		for (Entry<String, RoleProperty> entry : mospParams.getProperties().getRoleProperties().entrySet()) {
			// ロール情報取得
			RoleProperty roleProperty = entry.getValue();
			// デフォルトロール設定確認
			if (roleProperty.isSuper()) {
				return roleProperty.getKey();
			}
		}
		return roleCode;
	}
	
	/**
	 * この画面で使うVOを決めている。<br>
	 * @return 取得したVOインスタンス
	 */
	@Override
	protected FirstUserVo getSpecificVo() {
		return new FirstUserVo();
	}
	
}
