package batch.status;

import java.util.EnumSet;
import java.util.Optional;
import java.util.stream.Stream;


/**
 * ジョブ状態
 *
 * @author Tadashi Nakayama
 */
public enum JobState {
	/** 処理状況 処理依頼中 */
	ID_B_IRAI(10),
	/** 処理状況 処理依頼中(開始時間待ち) */
	ID_B_WAIT(11),
	/** 処理状況 処理中(シェル起動中) */
	ID_B_SH_START(20),
	/** 処理状況 処理中 */
	ID_B_EDIT(30),
	/** 処理状況 正常終了 */
	ID_B_NEND(40),
	/** 処理状況 対象データ無し */
	ID_B_NODATA(41),
	/** 処理状況 警告終了 */
	ID_B_WARNING(42),
	/** 処理状況 中止 */
	ID_B_CANCEL(43),
	/** 処理状況 異常終了 */
	ID_B_INVALID(44),
	/** 処理状況 異常終了（再起動済） */
	ID_B_INVALID_RERUN(45),
	/** 処理状況 中止依頼中 */
	ID_B_IRAI_CAN(50);

	/** 値 */
	private final int value;

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

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

	/**
	 * 実行中状態
	 * @return 実行中状態
	 */
	public static EnumSet<JobState> running() {
		return EnumSet.of(ID_B_EDIT, ID_B_SH_START);
	}

	/**
	 * リクエスト状態
	 * @return リクエスト状態
	 */
	public static EnumSet<JobState> requested() {
		return EnumSet.of(ID_B_IRAI, ID_B_WAIT);
	}

	/**
	 * リクエスト状態確認
	 * @param val 値
	 * @return リクエスト状態の場合 true を返す。
	 */
	public static boolean isRequest(final int val) {
		return requested().stream().anyMatch(js -> js.value() == val);
	}

	/**
	 * 実行中状態確認
	 * @param val 値
	 * @return 実行中状態の場合 true を返す。
	 */
	public static boolean isRunning(final int val) {
		return running().stream().anyMatch(js -> js.value() == val);
	}

	/**
	 * 終了状態確認
	 * @param val 値
	 * @return 終了状態の場合 true を返す。
	 */
	public static boolean isEnd(final int val) {
		return EnumSet.of(ID_B_NEND, ID_B_NODATA, ID_B_WARNING).
				stream().anyMatch(js -> js.value() == val);
	}

	/**
	 * キャンセル状態確認
	 * @param val 値
	 * @return キャンセル状態の場合 true を返す。
	 */
	public static boolean isCancel(final int val) {
		return ID_B_CANCEL.value() == val || ID_B_IRAI_CAN.value() == val;
	}

	/**
	 * エラー状態確認
	 * @param val 値
	 * @return エラー状態の場合 true を返す。
	 */
	public static boolean isError(final int val) {
		return ID_B_INVALID.value() == val;
	}

	/**
	 * キャンセル
	 * @param val 値
	 * @return 値に応じたキャンセル状態
	 */
	public static JobState cancel(final int val) {
		if (isRequest(val)) {
			return ID_B_CANCEL;
		} else if (isRunning(val)) {
			return ID_B_IRAI_CAN;
		}
		return null;
	}

	/**
	 * 値に一致したオブジェクトを返却する。
	 *
	 * @param val 値
	 * @return オブジェクト
	 */
	public static JobState valueOf(final int val) {
		final Optional<JobState> opt = Stream.of(JobState.values()).
						filter(js -> js.value() == val).findFirst();
		return opt.orElseThrow(() -> new IllegalArgumentException(String.valueOf(val)));
	}
}
