package project.web.processor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.chain2.Processing;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.chain.contexts.ServletActionContext;

import core.config.Factory;
import online.context.session.SessionScope;
import online.struts.action.UniForm;
import online.struts.chain.command.RequestCommand;
import online.struts.mapping.RequestMapping;
import project.master.MsgUtil;
import project.svc.auth.Authentication;

/**
 * アクションチェック
 *
 * @author Tadashi Nakayama
 * @version 1.0.0
 */
public final class AuthenticationProcessor implements RequestCommand {

	/** 再ログオン */
	public static final String ID_RELOGON = "RELOGON";

	/** タイムアウトメッセージ */
	private static final String MSGID_TIME_OUT = "ZZ000000003";
	/** 未ログオンメッセージ */
	private static final String MSGID_NOT_LOGON = "ZZ000000002";

	/** 多重ログイン可否 */
	private boolean multiple = false;

	/**
	 * 多重ログイン可否取得
	 *
	 * @return 多重ログイン可否
	 */
	public boolean isMultiple() {
		return this.multiple;
	}

	/**
	 * 多重ログイン可否設定
	 *
	 * @param val 多重ログイン可否
	 */
	public void setMultiple(final boolean val) {
		this.multiple = val;
	}

	/**
	 * @see online.struts.chain.command.RequestCommand
	 * #command(org.apache.struts.chain.contexts.ServletActionContext,
	 * online.struts.mapping.RequestMapping, online.struts.action.UniForm)
	 */
	@Override
	public Processing command(final ServletActionContext sac,
			final RequestMapping mapping, final UniForm uf) {
		if (sac.getForwardConfig() == null) {
			// ログオンとアクションチェック
			// セッションタイムアウトチェック
			final var af = checkLogon(sac.getRequest(), uf, mapping);
			if (af != null && ID_RELOGON.equals(af.getName())) {
				// メッセージ設定
				MsgUtil.putTopMessage(uf, MSGID_NOT_LOGON);
				sac.getResponse().setStatus(HttpServletResponse.SC_UNAUTHORIZED);
			}

			sac.setForwardConfig(af);
		}

		return Processing.CONTINUE;
	}

	/**
	 * ログオン確認処理
	 *
	 * @param request HTTPリクエスト
	 * @param uf 汎用フォーム
	 * @param mapping マッピング
	 * @return ActionForwardオブジェクト
	 */
	private ActionForward checkLogon(final HttpServletRequest request,
			final UniForm uf, final ActionMapping mapping) {
		// ログオンチェック
		final var su = SessionScope.getSessionUser(request);
		if (su == null) {
			MsgUtil.putTopMessage(uf, MSGID_TIME_OUT);
			return mapping.findForward(ID_RELOGON);
		}

		if (!this.multiple) {
			final var auth = Factory.create(Authentication.class);
			final var session = request.getSession(false);
			if (session == null || !auth.checkLogon(su.getUid(), session.getId())) {
				return mapping.findForward(ID_RELOGON);
			}

			// アクション時間設定
			auth.setActionTime(su.getUid(), uf.getPresent(), session.getId());
		}

		return null;
	}
}
