package org.fouram.core.util;

import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtils;
import org.fouram.constants.WebConstants;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

public class TreeUtil {

	public static <T> List<T> buildTreeSimple(List<T> list) throws Exception {
		return buildTreeNormal(list, "id", "parentId", "children", "orderBy", false, WebConstants.TOP_DEPART.toString());
	}

	public static <T> List<T> buildTreeNormal(List<T> list, String idProperty, String parentIdProperty,
			String childrenProperty, String sortProperty, boolean asc, String rootValue) throws Exception {
		// 转换成Map
		Map<String, List<T>> listMap = toMap(list, parentIdProperty);
		return buildSubTree(listMap, idProperty, parentIdProperty, childrenProperty, sortProperty, asc, rootValue);
	}

	private static <T> Map<String, List<T>> toMap(List<T> list, String parentIdProperty) throws Exception {
		// 转换成Map
		Map<String, List<T>> listMap = Maps.newHashMap();
		for (T t : list) {
			String parentId = PropertyUtils.getProperty(t, parentIdProperty).toString();
			List<T> subList = Lists.newArrayList();
			if (listMap.containsKey(parentId)) {
				subList = listMap.get(parentId);
			}
			subList.add(t);
			listMap.put(parentId, subList);
		}
		return listMap;
	}

	/**
	 * 递归不断获取子节点，放到children属性
	 *
	 * @param <T>
	 * @param listMap
	 * @param idProperty
	 * @param parentIdProperty
	 * @param childrenProperty
	 * @param sortProperty
	 * @param asc
	 * @param parentValue
	 * @return
	 * @throws Exception
	 */
	private static <T> List<T> buildSubTree(Map<String, List<T>> listMap, String idProperty, String parentIdProperty,
			String childrenProperty, String sortProperty, boolean asc, String parentValue) throws Exception {
		List<T> result = new LinkedList<>();
		List<T> subList = new LinkedList<>();
		if (listMap.containsKey(parentValue.toString())) {
			subList = listMap.get(parentValue.toString());
		}
		Collections.sort(subList, new Comparator<Object>() {
			@Override
			public int compare(Object o1, Object o2) {
				Object sort1 = "0";
				Object sort2 = "0";
				try {
					sort1 = PropertyUtils.getProperty(o1, sortProperty);
					sort2 = PropertyUtils.getProperty(o2, sortProperty);
				} catch (Exception e) {
					LoggerUtil.error(e);
				}
				if (asc) {
					return Integer.valueOf(sort1.toString()).intValue() - Integer.valueOf(sort2.toString()).intValue();
				} else {
					return Integer.valueOf(sort2.toString()).intValue() - Integer.valueOf(sort1.toString()).intValue();
				}
			}
		});
		for (int i = 0; i < subList.size(); i++) {
			T obj = subList.get(i);
			String id = PropertyUtils.getProperty(obj, idProperty).toString();
			PropertyUtils.setProperty(obj, childrenProperty,
					buildSubTree(listMap, idProperty, parentIdProperty, childrenProperty, sortProperty, asc, id));
			result.add(obj);
		}
		return result;
	}
}
