/*
 * Copyright 2006 Takahiro Nakamura.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package woolpack.bool;

import java.util.Collection;
import java.util.regex.Pattern;

import woolpack.fn.FixFn;
import woolpack.fn.Fn;
import woolpack.fn.IfFn;

/**
 * ユーティリティです。
 * 型推論で表記を簡略するためのスタティックメソッドと変数を含みます。
 * 
 * @author nakamura
 *
 */
public final class BoolUtils {

	/**
	 * 引数が{@link Throwable}のサブクラスでないことを評価する{@link Fn}です。
	 */
	public static final Fn<Object, Boolean> NOT_THROWABLE = not(matchObject(Throwable.class));
	
	public static final NotFn NOT = new NotFn();
	public static final NotEmptyChecker NOT_EMPTY = new NotEmptyChecker();
	public static final BooleanConverter TO_BOOLEAN = new BooleanConverter();
	
	private BoolUtils() {
	}
	
	public static <C> And<C> and() {
		return new And<C>();
	}
	
	public static <C> AndAnd<C> andand() {
		return new AndAnd<C>();
	}
	
	public static <C> BoolSeq<C> boolSeq(
			final BooleanOperator<C> operator,
			final Iterable<? extends Fn<? super C, Boolean>> iterable) {
		return new BoolSeq<C>(operator, iterable);
	}
	
	public static <C> BoolSeq<C> boolSeq(
			final Iterable<? extends Fn<? super C, Boolean>> iterable) {
		return new BoolSeq<C>(iterable);
	}
	
	public static <C extends Comparable<C>> CompareFn<C> compare(final C value) {
		return new CompareFn<C>(value);
	}
	
	public static ContainsAllChecker containsAll(final Collection<?> value) {
		return new ContainsAllChecker(value);
	}
	
	public static ContainsChecker contains(final Collection<?> value) {
		return new ContainsChecker(value);
	}
	
	public static <C> Eq<C> eq() {
		return new Eq<C>();
	}
	
	public static <C> EqEq<C> eqeq() {
		return new EqEq<C>();
	}
	
	public static EqualsChecker checkEquals(final Object value) {
		return new EqualsChecker(value);
	}
	
	public static <C extends Comparable<C>> MaxChecker<C> checkMax(final C value) {
		return new MaxChecker<C>(value);
	}
	
	public static MaxLengthChecker checkMaxLength(final int value) {
		return new MaxLengthChecker(value);
	}
	
	public static <C extends Comparable<C>> MinChecker<C> checkMin(final C value) {
		return new MinChecker<C>(value);
	}
	
	public static MinLengthChecker checkMinLength(final int value) {
		return new MinLengthChecker(value);
	}
	
	public static <C> NotDelegator<C> not(final Fn<? super C, Boolean> fn) {
		return new NotDelegator<C>(fn);
	}
	
	public static ObjectMatcher matchObject(final Object value) {
		return new ObjectMatcher(value);
	}
	
	public static <C> Or<C> or() {
		return new Or<C>();
	}
	
	public static <C> OrOr<C> oror() {
		return new OrOr<C>();
	}
	
	public static RegExpChecker checkRegExp(final Pattern pattern) {
		return new RegExpChecker(pattern);
	}
	
	/**
	 * 評価結果が{@link Boolean#TRUE}の場合に委譲する{@link Fn}を返します。
	 * @param <C>
	 * @param ifFn
	 * @param trueFn
	 * @return 評価結果が{@link Boolean#TRUE}の場合に委譲する{@link Fn}。
	 */
	public static <C> IfFn<C, Boolean> ifTrue(
			final Fn<? super C, ?> ifFn,
			final Fn<? super C, ? extends Boolean> trueFn) {
		return new IfFn<C, Boolean>(ifFn, trueFn, new FixFn<C, Boolean>(false));
	}
	
	/**
	 * 評価結果が{@link Boolean#TRUE}でない場合に委譲する{@link Fn}を返します。
	 * @param <C>
	 * @param ifFn
	 * @param falseFn
	 * @return 評価結果が{@link Boolean#TRUE}でない場合に委譲する{@link Fn}。
	 */
	public static <C> IfFn<C, Boolean> ifNot(
			final Fn<? super C, ?> ifFn,
			final Fn<? super C, ? extends Boolean> falseFn) {
		return new IfFn<C, Boolean>(ifFn, new FixFn<C, Boolean>(true), falseFn);
	}
}
