/*
 * MosP - Mind Open Source Project         http://www.mosp.jp/
 * Copyright (C) 1987-2008 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.action;

import java.util.Date;

import jp.mosp.common.CommonConst;
import jp.mosp.common.UserAuthUtility;
import jp.mosp.common.common.BaseVo;
import jp.mosp.common.common.LogUtility;
import jp.mosp.common.common.MospConst;
import jp.mosp.common.common.MospException;
import jp.mosp.common.common.MospUtility;
//import jp.mosp.common.dao.CtAccountDao;
//import jp.mosp.common.dao.MosPUserDao;
import jp.mosp.common.dto.CmAspUserDto;
//import jp.mosp.common.dto.CmUserDto;
//import jp.mosp.common.dto.CtAccountDto;
import jp.mosp.common.dto.MosPUserDto;
import jp.mosp.common.vo.MosPLoginVo;

public class MosPAuthAction extends MosPAction {

	/**
	 * コンストラクタ
	 */
	public MosPAuthAction() {
		super();
		setNeedUser(false);
		// ログイン画面でのセッション切断無視
		setNeedAspUser(false);
		setCheckProcSeq(false);
		setNeedSession(false);
	}

	/**
	 * アクション
	 */
	public void action() throws Exception {
		// パラメータの取得
		MosPLoginVo vo = getInitVo();
		// 初期処理
		init(vo);
		// DBコネクションの取得
		getConnection();
		// 認証処理
		login(vo);
		// 後処理
		afterProcess();
	}

	protected MosPLoginVo getInitVo() {
		return new MosPLoginVo();
	}

	/**
	 * 初期処理
	 * @param vo			対象VO
	 * @throws Exception
	 */
	protected void init(MosPLoginVo vo) throws Exception {
		vo.initVo(cfg, msg, cmd, aspUser, user);
		vo.setParams(request);
		// ASPユーザー取得(設定ファイルのASP設定で判断)
		setAspUser(vo);
		// パラメータの妥当性確認
		if (!vo.validate()) {
			// パラメータ不正の場合
			setVo(vo);
			setUrl(vo.getRetUrl());
			throw new MospException(MospConst.EX_PARAMS_INVALID);
		}		
	}

	/**
	 * ASPユーザー取得(設定ファイルのASP設定で判断)
	 * @param vo			対象VO
	 * @throws Exception
	 */
	private void setAspUser(MosPLoginVo vo) throws Exception {
		// ASPユーザー取得(設定ファイルのASP設定で判断)
		switch (MospUtility.getAspFlag(cfg)) {
		case 0:
		case 1:
			// 0：ASP(xユーザー:1アプリ)
			// 1：ASP(1ユーザー:1アプリ)
			// ASPユーザー情報をセット(セッションから取得)
			session = request.getSession(false);
			aspUser = (CmAspUserDto)session.getAttribute(MospConst.ATT_ASPUSER);
			BaseVo aspVo = (BaseVo)request.getAttribute(MospConst.ATT_VO);
			// returnUrl設定
			vo.setRetUrl(aspVo.getRetUrl());
			break;
		case 2:
			// 2：非ASP
			// ASPユーザー情報をセット(ログイン画面でのセッション切断無視)
			createAspUser();
			break;
		default:
			throw new MospException(MospConst.EX_ASP_PROPERTIES);
		}
	}

	/**
	 * 認証処理
	 * @param vo ログイン画面のVO
	 */
	/*	
	public void login(MosPLoginVo vo) throws Exception {
		// DBコネクションの取得
		getConnection();
		// ユーザーの取得
		MosPUserDto dto = new MosPUserDto();
		CmUserDto cmUserDto = new CmUserDto();
		dto.setUserId(vo.getUserId());
		cmUserDto.setUserId(vo.getUserId());
		MosPUserDao dao = new MosPUserDao();
		dao.initDao(cfg, cmd, aspUser, cmUserDto, conn);
		dto = dao.findForRegistered(vo.getUserId());
		// アカウント情報の取得準備
		CtAccountDao ctAccountDao;
		CtAccountDto ctAccountDto;
		if (dto != null) {
			// ユーザーが取得できた場合
			// 削除チェック
			if (dto.getDeleteFlag() == 1) {
				vo.addErrMessage(MospUtility.getMessage(msg, MospConst.MSG_AUTH_FAILED, ""));
				setVo(vo);
				setUrl(vo.getRetUrl());
				throw new MospException(MospConst.EX_AUTH_DELETED);
			}
			// アカウント情報の取得
			ctAccountDao = new CtAccountDao();
			ctAccountDao.initDao(cfg, cmd, aspUser, cmUserDto, conn);
			ctAccountDto = ctAccountDao.findCtAccountForUserId(dto.getUserId());
			if (ctAccountDto == null) {
				// アカウント情報が取得できなかった場合
				// アカウント情報を作成
				ctAccountDto = new CtAccountDto();
				ctAccountDto.setUserId(dto.getUserId());
				ctAccountDto.setAttempt(1);
				ctAccountDao.insert(ctAccountDto);
			} else {
				// アカウント情報が取得できた場合
				// ログイン試行回数確認
				int maxAttempt = Integer.parseInt(cfg.getProperty(MospConst.PPT_ACC_ATTEMPT));
				if (ctAccountDto.getAttempt() >= maxAttempt) {
					// ログイン試行回数が設定値より大きい場合
					// 再試行インターバルを確認
					long interval = Long.parseLong(cfg.getProperty(MospConst.PPT_ACC_INTERVAL)) * 1000;
					Date date = new Date(ctAccountDto.getUpdateDate().getTime() + interval);
					if (date.compareTo(new Date()) > 0) {
						// 再試行インターバルを経ずにログイン試行した場合
						// 試行回数のインクリメント
						ctAccountDto.incrementAttempt();
						ctAccountDao.update(ctAccountDto);
						commit();
						// アカウントロック例外を発行
						vo.addErrMessage(MospUtility.getMessage(msg, MospConst.MSG_ACCOUNT_LOCK, ""));
						setVo(vo);
						setUrl(vo.getRetUrl());
						throw new MospException(MospConst.EX_ACCOUNT_LOCK);
					}
				}
			}
		} else {
			// ユーザーが取得できなかった場合
			vo.addErrMessage(MospUtility.getMessage(msg, MospConst.MSG_AUTH_FAILED, ""));
			setVo(vo);
			setUrl(vo.getRetUrl());
			throw new MospException(MospConst.EX_AUTH_NOT_EXIST);
		}
		// パスワードによる認証
		if (dto.getPassword().equals(MospUtility.getDigest(vo.getPass()))) {
			// 認証成功
			// アカウント情報の更新
			ctAccountDto.setAttempt(0);
			ctAccountDao.update(ctAccountDto);
			// ユーザー情報の設定
			dto.setPassword("");
			cmUserDto.setUserId(dto.getUserId());
			cmUserDto.setPassword(dto.getPassword());
			cmUserDto.setUserName(dto.getUserName());
			cmUserDto.setCommonCss("");
			cmUserDto.setMospAuthority(dto.getAuthority());
			cmUserDto.setPayrollAuthority("");
			cmUserDto.setZaimuAuthority("");
			cmUserDto.setSalesAuthority("");
			cmUserDto.setExpenseAuthority("");
			cmUserDto.setExt1Authority("");
			cmUserDto.setExt2Authority("");
			cmUserDto.setExt3Authority("");
			cmUserDto.setExt4Authority("");
			cmUserDto.setExt5Authority("");
			cmUserDto.setDeleteFlag(dto.getDeleteFlag());
			this.user = cmUserDto;

			// 基本情報取得及び設定
			// 未実装(都度取得するようにするかは、未定)

			// 入社日以降しかログインできないようにする。
			getInfo(user.getUserId());
			Date entranceDate;
			if (chkExistDto(mKihon)) {
				entranceDate = util.convIntegerDateToDate(mKihon.getNyDate());
			} else if (dto.getAuthority().equals(CommonConst.AUTHORITY_ADMIN)) {
				entranceDate = new Date(0);
			} else {
				entranceDate = null;
			}
			if (!chkExistObject(entranceDate) || (util.getSystemDate().compareTo(entranceDate) < 0)) {
				// ログイン画面へ戻る
				vo.addErrMessage(MospUtility.getMessage(msg, MospConst.MSG_AUTH_FAILED, ""));
				setVo(vo);
				setUrl(vo.getRetUrl());
				throw new MospException(MospConst.EX_AUTH_FAILED);
			}
		} else {
			// 認証失敗
			// アカウント情報の更新
			ctAccountDto.incrementAttempt();
			ctAccountDao.update(ctAccountDto);
			commit();
			// ログイン画面へ戻る
			// ユーザーが取得できなかった場合
			vo.addErrMessage(MospUtility.getMessage(msg, MospConst.MSG_AUTH_FAILED, ""));
			setVo(vo);
			setUrl(vo.getRetUrl());
			throw new MospException(MospConst.EX_AUTH_FAILED);
		}
		// DBコネクションのコミット
		commit();
	}
	 */
	protected void login(MosPLoginVo vo) throws Exception {
		UserAuthUtility authUtility = new UserAuthUtility(cfg, cmd, aspUser, conn);
		authUtility.login(vo.getUserId(), vo.getPass());
		// 認証が失敗している場合
		if (authUtility.isErrMessage()) {
			// コミット
			commit();
			// エラーメッセージの設定
			vo.addErrMessage(MospUtility.getMessage(msg, authUtility.getErrMessageCode(), ""));
			setVo(vo);
			setUrl(vo.getRetUrl());
			throw new MospException(authUtility.getMosPExceptionCode());
		}
		this.user = authUtility.getCmUserDto();
		// 次のページへ遷移処理
		setNextPage(getUserInfo(vo.getUserId()), vo);
	}

	/**
	 * 次ページ遷移処理
	 * @param dto			対象DTO
	 * @param vo			対象VO
	 * @throws Exception
	 */
	protected void setNextPage(MosPUserDto dto, MosPLoginVo vo) throws Exception {
		// 初期コマンド設定
		String nextCmd = "C1060";
		// パスワード有効期限確認
		int passTerm = getPasswordTerm();
		boolean validPassWord = true;
		// パスワード有効期限を過ぎていたら、パスワード変更画面に遷移する。
		// ユーザーIDとパスワードが同じ場合、パスワード変更画面に遷移する。
		if (isExpirePassWord(passTerm, dto.getUpdateDate())
				|| isDefaultPassWord(dto.getUserId(), vo.getPass())	
		) {
			nextCmd = jp.mosp.common.action.MosPPasswordAction.CMD_PASSWORD_FORCE_CHANGE;
			validPassWord = false;
		}
		// adminの場合CSSと初期コマンドを変更
		if (dto.getAuthority().equals(CommonConst.AUTHORITY_ADMIN) && validPassWord) {
			user.setCommonCss(CommonConst.CSS_ADMIN);
			nextCmd = vo.CMD_MENU_SYSTEM2;
		}
		setNextCmd(nextCmd);
		// サーブレットへ
		setUrl(MospConst.URL_SRV);
	}

	/**
	 * パスワード有効期限チェック
	 * @param passTerm		有効期限期間
	 * @param updateDate	更新日時
	 * @return
	 * <p>
	 * 有効期限を超過したらtrue、そうでない場合false
	 * </p>
	 */
	private boolean isExpirePassWord(int passTerm, Date updateDate) {
		if (passTerm > 0 
				&& util.getSystemDate().compareTo(util.addDay(updateDate, passTerm)) > 0
		) {
			return true;
		}
		return false;
	}

	/**
	 * デフォルトパスワードチェック
	 * @param userid			対象ユーザID
	 * @param inputPassWord		対象入力パスワード
	 * @return
	 * <p>
	 * デフォルトパスワードの場合true、そうでない場合false
	 * </p>
	 * @throws Exception
	 */
	private boolean isDefaultPassWord(String userid, String inputPassWord) throws Exception {
		if (MospUtility.getDigest(MospUtility.getDigest(userid))
				.equals(MospUtility.getDigest(inputPassWord))
		) {
			return true;
		}
		return false;
	}

	/**
	 * 後処理
	 */
	protected void afterProcess() {
		// セッションの再取得
		if (session != null) {
			session.invalidate();
		}
		session = request.getSession(true);
		// ユーザー情報をセット
		session.setAttribute(MospConst.ATT_ASPUSER, aspUser);
		session.setAttribute(MospConst.ATT_USER, user);
		request.setAttribute(MospConst.ATT_USER, user);
		// ログ出力
		LogUtility.log(request, 4, MospConst.LOG_MOSPINF, MospConst.LOG_MSG_LOGIN);
	}

}
