package core.util.bean;

import java.nio.channels.IllegalSelectorException;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * 条件処理
 *
 * @author Tadashi Nakayama
 * @param <T> ジェネリックス
 */
public final class Deal<T> {
	/** 入力値 */
	private final T input;
	/** 条件結果 */
	private Boolean bool;

	/**
	 * コンストラクタ
	 * @param val 入力値
	 */
	public Deal(final T val) {
		this.input = val;
	}

	/**
	 * 条件成立時
	 * @param predicate 条件
	 * @return Deal
	 */
	public Deal<T> match(final Predicate<? super T> predicate) {
		if (this.bool == null) {
			this.bool = Boolean.valueOf(predicate.test(this.input));
		}
		return this;
	}

	/**
	 * 条件不成立時
	 * @param predicate 条件
	 * @return Deal
	 */
	public Deal<T> negate(final Predicate<? super T> predicate) {
		return match(predicate.negate());
	}

	/**
	 * 条件真時処理
	 * @param action 処理
	 * @return Deal
	 */
	public Deal<T> then(final Consumer<? super T> action) {
		if (eval()) {
			action.accept(this.input);
		}
		return this;
	}

	/**
	 * 変換処理
	 * 条件が真の場合、変換される
	 * @param mapper 変換ラムダ式
	 * @return 条件真：変換後値 条件偽：入力値
	 */
	public T trans(final Function<? super T, ? extends T> mapper) {
		return eval() ? mapper.apply(this.input) : this.input;
	}

	/**
	 * 条件値取得
	 * @return 条件値
	 */
	public boolean eval() {
		if (this.bool == null) {
			throw new IllegalSelectorException();
		}
		return this.bool.booleanValue();
	}

	/**
	 * 入力値取得
	 * @return 入力値
	 */
	public T val() {
		return this.input;
	}

	//	/**
	//	 * 条件偽時処理
	//	 * @param action 処理
	//	 * @return Deal
	//	 */
	//	public Deal<T> els(final Consumer<? super T> action) {
	//		if (!eval()) {
	//			action.accept(this.input);
	//		}
	//		return this;
	//	}

	//	/**
	//	 * 変換処理
	//	 * 条件が偽の場合、変換される
	//	 * @param mapper 変換ラムダ式
	//	 * @return 条件偽：変換後値 条件真：入力値
	//	 */
	//	public T others(final Function<? super T, ? extends T> mapper) {
	//		return eval() ? this.input : mapper.apply(this.input);
	//	}
}
