package cn.superdesk.uniorder.common.lamda;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;

/**
 * @Description: AnLamdaUtils
 * @Author: linjinyu
 * @CreateDate: 6/23/20 5:14 PM
 * @UpdateUser: linjinyu
 * @UpdateDate: 6/23/20 5:14 PM
 * @UpdateRemark: 修改内容
 * @Version: 1.0
 */
public class AnLamdaUtils {

	/**
	 * 工具方法
	 * ForEachUtils.forEach(0, list, (index, item) -> {
	 *
	 * });
	 * @param <T>
	 * @param startIndex 开始遍历的索引
	 * @param elements 集合
	 * @param action
	 */
	public static <T> void forEach(int startIndex,Iterable<? extends T> elements, BiConsumer<Integer, ? super T> action) {
		Objects.requireNonNull(elements);
		Objects.requireNonNull(action);
		if(startIndex < 0) {
			startIndex = 0;
		}
		int index = 0;
		for (T element : elements) {
			index++;
			if(index <= startIndex) {
				continue;
			}

			action.accept(index-1, element);
		}
	}

	// 工具方法

	/**
	 * issuesOrderSns.forEach(AnLamdaUtils.consumerWithIndex((orderSn, index) -> {
	 *
	 * 			Map<String, String> temp = new HashMap<>();
	 * 			temp.put("index", AnStringUtils.getString(index));
	 * 			temp.put("orderSn", orderSn);
	 *
	 * 			issuesOrderSnsListMap.add(temp);
	 *                }));
	 * @param consumer
	 * @param <T>
	 * @return
	 */
	public static <T> Consumer<T> consumerWithIndex(BiConsumer<T, Integer> consumer) {
		class Obj {
			int i;
		}
		Obj obj = new Obj();
		return t -> {
			int index = obj.i++;
			consumer.accept(t, index);
		};
	}

	/**
	 * distinctByKey 自己定义 针对属性去重
	 * <p>
	 * usage:
	 * List<InvoiceOrder> invoiceOrderList = invoiceOrderMapper.selectByExample(example);
	 * <p>
	 * if (AnCollectionUtils.isNotEmpty(invoiceOrderList)) {
	 * // 得出受影响的对账单 ids
	 * affectedAccountingOrderIds = invoiceOrderList.stream().filter(AnLamdaUtils.distinctByKey(o -> o.getDzId())).map(o -> o.getDzId()).collect(Collectors.toList());
	 * }
	 *
	 * @param keyExtractor
	 * @param <T>
	 * @return
	 */
	public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
		Map<Object, Boolean> seen = new ConcurrentHashMap<>();
		return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
	}


	public static <T extends Object> T filter(List<T> objs, Predicate<T> predicate) {
		return objs.stream()
				.filter(predicate)
				.findAny()
				.orElse(null);
	}


	/**
	 * 根据多个判断条件, 对list数据按优先级排序
	 * list 需要过滤的数据
	 * predicates 多个判断条件
	 */
	public static <T extends Object> List<T> filters(List<T> list, List<Predicate<T>> predicates) {

		List<T>   resultList = new ArrayList();
		Stream<T> stream     = list.stream();

		// 循环判断条件list
		for (int i = 0, psize = predicates.size(), lsize = list.size(); resultList.size() < lsize && i < psize; i++) {

			Predicate<T> predicate = predicates.get(i);
			// stream.filter 过滤掉 符合条件的, 同时把符合条件的添加到 待返回的list
			stream = stream.filter(e -> {
				if (predicate.test(e)) {
					resultList.add(e);
					return false;
				}
				return true;
			});
		}
		long count = stream.count();

		return resultList;
	}


}
