package project.svc.auth;

import java.sql.Timestamp;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import core.util.DateUtil;

/**
 * ログオン情報保持
 *
 * @author Tadashi Nakayama
 * @version 1.0.0
 */
public final class SessionInfo {
	/**
	 * ログオフ状態
	 *
	 * @author Tadashi Nakayama
	 */
	public enum LogoffType {
		/** ログオフ形式（通常） */
		TYPE_NORMAL(10),
		/** ログオフ形式（強制） */
		TYPE_FORCE(20),
		/** ログオフ形式（タイムアウト） */
		TYPE_TIMEOUT(30);

		/** 値 */
		private final int value;

		/**
		 * コンストラクタ
		 *
		 * @param val 値
		 */
		LogoffType(final int val) {
			this.value = val;
		}

		/**
		 * 値取得
		 *
		 * @return 値
		 */
		public int value() {
			return this.value;
		}
	}

	/** 前回ログオフ日時 */
	private Timestamp logoffDateTime;
	/** ログオン日時 */
	private Timestamp logonDateTime;
	/** 最終処理日時 */
	private Timestamp shoriDateTime;
	/** ログオンセション */
	private String logonSession;
	/** チケット */
	private String ticket;
	/** 前回ログオフタイプ */
	private LogoffType logoffType;
	/** インターバル */
	private int interval;
	/** 現在日時 */
	private Timestamp datetime;

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

	/**
	 * コンストラクタ
	 *
	 * @param session ログオンセション
	 * @param last 最終処理日時
	 * @param tkt チケット
	 * @param logon ログオン日時
	 * @param logoff ログオフ日時
	 */
	public SessionInfo(final String session, final Timestamp last,
			final String tkt, final Timestamp logon, final Timestamp logoff) {
		this.logonSession = session;
		this.ticket = tkt;
		this.shoriDateTime = DateUtil.copyOf(last);
		this.logonDateTime = DateUtil.copyOf(logon);
		this.logoffDateTime = DateUtil.copyOf(logoff);
		this.logoffType = LogoffType.TYPE_NORMAL;
	}

	/**
	 * 前回ログオフ状態取得
	 *
	 * @param actionTime アクション文字列
	 * @param timeout タイムアウト時間(秒)
	 * @param now 現在日付オブジェクト
	 * @return 前回ログオフ情報
	 */
	private LogoffType getLogoffType(
			final Timestamp actionTime, final int timeout, final Timestamp now) {
		// タイムアウトしているか
		var ret = LogoffType.TYPE_NORMAL;
		if (actionTime != null) {
			final var sum = actionTime.getTime() + TimeUnit.SECONDS.toMillis(timeout);
			if (now != null && now.getTime() > sum) {
				ret = LogoffType.TYPE_TIMEOUT;
			} else {
				ret = LogoffType.TYPE_FORCE;
			}
		}
		return ret;
	}

	/**
	 * 前回ログオフ時間取得
	 *
	 * @param actionTime アクション文字列
	 * @param timeout タイムアウト時間(秒)
	 * @param now 現在日付オブジェクト
	 * @return 前回ログオフ情報
	 */
	private Timestamp getLogoffTimestamp(
			final Timestamp actionTime, final int timeout, final Timestamp now) {
		// タイムアウトしているか
		Timestamp ret = null;
		if (actionTime != null) {
			final var sum = actionTime.getTime() + TimeUnit.SECONDS.toMillis(timeout);
			if (now != null && now.getTime() > sum) {
				ret = new Timestamp(sum);
			} else {
				ret = now;
			}
		}
		return ret;
	}

	/**
	 * インターバル設定
	 *
	 * @param val インターバル
	 */
	public void setInterval(final int val) {
		this.interval = val;
	}

	/**
	 * 現在日時設定
	 *
	 * @param val 現在日時
	 */
	public void setDateTime(final Timestamp val) {
		this.datetime = DateUtil.copyOf(val);
	}

	/**
	 * ログオフタイプ取得
	 *
	 * @return ログオフタイプ
	 */
	public LogoffType getLogoffType() {
		if (!Objects.toString(this.logonSession, "").isEmpty()) {
			this.logoffType = getLogoffType(
					this.shoriDateTime, this.interval, this.datetime);
		}
		return this.logoffType;
	}

	/**
	 * ログオン日時取得
	 *
	 * @return ログオン日時
	 */
	public Timestamp getLogonDateTime() {
		return DateUtil.copyOf(this.logonDateTime);
	}

	/**
	 * ログオフ日時取得
	 *
	 * @return ログオフ日時
	 */
	public Timestamp getLogoffDateTime() {
		if (!Objects.toString(this.logonSession, "").isEmpty()) {
			this.logoffDateTime = getLogoffTimestamp(
					this.shoriDateTime, this.interval, this.datetime);
		}
		return DateUtil.copyOf(this.logoffDateTime);
	}

	/**
	 * ログオンセション取得
	 *
	 * @return ログオンセション
	 */
	public String getLogonSession() {
		return this.logonSession;
	}

	/**
	 * 最終処理日時取得
	 *
	 * @return 最終処理日時
	 */
	public Timestamp getShoriDateTime() {
		return DateUtil.copyOf(this.shoriDateTime);
	}

	/**
	 * チケット取得
	 *
	 * @return チケット
	 */
	public String getTicket() {
		return this.ticket;
	}
}
