package com.winsun.utils;

import org.apache.commons.lang.StringUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 数结构用于保存Excel表头， 主要用于需要合并单元格的表头
 *
 * @author ZERO
 *
 */
public class TreeNode implements Serializable {
	/**
	 *
	 */
	private static final long serialVersionUID = 1L;
	private int parentId;
	private int selfId;
	protected int level;
	protected int leafSize;//
	protected String key;
	protected String nodeName;
	protected TreeNode parentNode;
	protected int color;
	protected List<TreeNode> childList;
	protected String desensitizationType; //数据脱敏类型
	protected Map<String, String> desensitizationTypeMap; //数据脱敏集合
	protected String cellFormat; //数据脱敏类型
	protected Map<String, String> cellFormatMap; //数据脱敏集合

	public TreeNode() {
		initChildList();
	}

	public TreeNode(String name) {
		this.setNodeName(name);
		initChildList();
	}

	public TreeNode(String name, TreeNode parentNode) {
		this(name);
		if (parentNode != null) {
			this.setParentNode(parentNode);
			this.setParentId(parentNode.selfId);
		}
	}

	public TreeNode(int id, TreeNode parentNode) {
		this(null, parentNode);
		this.setSelfId(id);
	}

	public TreeNode(int id, String name, TreeNode parentNode) {
		this.setSelfId(id);
		this.setNodeName(name);
		if (parentNode != null) {
			this.setParentNode(parentNode);
			this.setParentId(parentNode.selfId);
			parentNode.addChildNode(this);
		}
		initChildList();
	}

	public TreeNode(int id, String name, String key, TreeNode parentNode) {
		this(id, name, parentNode);
		this.setKey(key);
	}

	public TreeNode(int id, String name, String key, TreeNode parentNode, String desensitizationType) {
		this(id, name, key, parentNode);
		this.setDesensitizationType(desensitizationType);
	}

	public TreeNode(int id, String name, TreeNode parentNode, int color) {
		this(id, name, parentNode);
		this.setColor(color);
	}

	public TreeNode(int id, String name, String key, TreeNode parentNode, int color) {
		this(id, name, key, parentNode);
		this.setColor(color);
	}

	public TreeNode(int id, String name, String key, TreeNode parentNode, int color, String desensitizationType) {
		this(id, name, key, parentNode, color);
		this.setDesensitizationType(desensitizationType);
	}

	public TreeNode(TreeNode parentNode) {
		if (parentNode != null) {
			this.setParentNode(parentNode);
			this.setParentId(parentNode.selfId);
			parentNode.addChildNode(this);
		}
		initChildList();
	}

	public boolean isLeaf() {
		if (childList == null) {
			return true;
		}
		if (childList.isEmpty()) {
			return true;
		}
		return false;
	}

	/* 插入一个child节点到当前节点中 */
	public void addChildNode(TreeNode treeNode) {
		initChildList();
		childList.add(treeNode);
		treeNode.setParentNode(this);
	}

	public void initChildList() {
		if (childList == null) {
			childList = new ArrayList<TreeNode>();
		}
	}

	public boolean isValidTree() {
		return true;
	}

	/* 返回当前节点的父辈节点集合 */
	public List<TreeNode> getElders() {
		List<TreeNode> elderList = new ArrayList<TreeNode>();
		TreeNode parentNode = this.getParentNode();
		if (parentNode == null) {
			return elderList;
		}
		elderList.add(parentNode);
		elderList.addAll(parentNode.getElders());
		return elderList;
	}

	/* 返回当前节点的晚辈集合 */
	public List<TreeNode> getJuniors() {
		List<TreeNode> juniorList = new ArrayList<TreeNode>();
		List<TreeNode> childList = this.getChildList();
		if (childList == null) {
			return juniorList;
		}
		int childNumber = childList.size();
		for (int i = 0; i < childNumber; i++) {
			TreeNode junior = childList.get(i);
			juniorList.add(junior);
			juniorList.addAll(junior.getJuniors());
		}
		return juniorList;
	}

	/**
	 * 获取指定层节点，层数索引从0开始
	 *
	 * @author SongBaoYu
	 * @return
	 */
	public static List<TreeNode> getNodesByLevel(TreeNode root, int lvl) {
		List<TreeNode> resList = new ArrayList<TreeNode>();
		if (lvl < 0)// 越界检查
			return resList;
		resList.add(root);
		for (int i = 0; i < lvl; ++i) {
			resList = getNextLevelNodes(resList);
		}
		return resList;
	}

	/**
	 * 返回当前层的下一层节点
	 *
	 * @author SongBaoYu
	 * @param currLevelNodes
	 * @return
	 */
	public static List<TreeNode> getNextLevelNodes(List<TreeNode> currLevelNodes) {
		List<TreeNode> resList = new ArrayList<TreeNode>();
		for (TreeNode currNode : currLevelNodes) {
			List<TreeNode> childList = currNode.getChildList();
			for (TreeNode node : childList) {
				if (StringUtils.isBlank(node.getKey()))
					resList.add(node);
			}
		}
		return resList;
	}

	/* 返回当前节点的孩子集合 */
	public List<TreeNode> getChildList() {
		return childList;
	}

	/* 删除节点和它下面的晚辈 */
	public void deleteNode() {
		TreeNode parentNode = this.getParentNode();
		int id = this.getSelfId();
		if (parentNode != null) {
			parentNode.deleteChildNode(id);
		}
	}

	/* 删除当前节点的某个子节点 */
	public void deleteChildNode(int childId) {
		List<TreeNode> childList = this.getChildList();
		int childNumber = childList.size();
		for (int i = 0; i < childNumber; i++) {
			TreeNode child = childList.get(i);
			if (child.getSelfId() == childId) {
				childList.remove(i);
				return;
			}
		}
	}

	/* 动态的插入一个新的节点到当前树中 */
	public boolean insertJuniorNode(TreeNode treeNode) {
		int juniorParentId = treeNode.getParentId();
		if (this.parentId == juniorParentId) {
			addChildNode(treeNode);
			return true;
		}
		List<TreeNode> childList = this.getChildList();
		int childNumber = childList.size();
		boolean insertFlag;

		for (int i = 0; i < childNumber; i++) {
			TreeNode childNode = childList.get(i);
			insertFlag = childNode.insertJuniorNode(treeNode);
			if (insertFlag == true)
				return true;
		}
		return false;
	}

	/* 找到一颗树中某个节点 */
	public TreeNode findTreeNodeById(int id) {
		if (this.selfId == id)
			return this;
		if (childList.isEmpty() || childList == null) {
			return null;
		}
		int childNumber = childList.size();
		for (int i = 0; i < childNumber; i++) {
			TreeNode child = childList.get(i);
			TreeNode resultNode = child.findTreeNodeById(id);
			if (resultNode != null) {
				return resultNode;
			}
		}
		return null;
	}

	/* 找到一颗树中某个节点 */
	public TreeNode findTreeNodeByKey(String key) {
		if (key.equals(this.getKey()))
			return this;
		if (isLeaf()) {
			return null;
		}
		int childNumber = childList.size();
		for (int i = 0; i < childNumber; i++) {
			TreeNode child = childList.get(i);
			TreeNode resultNode = child.findTreeNodeByKey(key);
			if (resultNode != null) {
				return resultNode;
			}
		}
		return null;
	}

	/* 遍历一棵树，层次遍历 */
	public void traverse() {
		if (selfId < 0)
			return;
		// print(this.selfId);
		System.out.print(this.level + " ");
		if (this.isLeaf())
			return;
		int childNumber = childList.size();
		for (int i = 0; i < childNumber; i++) {
			TreeNode child = childList.get(i);
			child.traverse();
		}
	}

	public void traverseNode() {
		if (selfId < 0)
			return;
		// print(this.selfId);
		System.out.print(this.nodeName + ",");
		if (this.isLeaf())
			return;
		int childNumber = childList.size();
		for (int i = 0; i < childNumber; i++) {
			TreeNode child = childList.get(i);
			child.traverseNode();
		}
	}

	/**
	 * 从左到右获取叶子的key
	 */
	public List<String> getKeyList() {
		List<String> keyList = new ArrayList<String>();
		List<TreeNode> nodeList = this.getJuniors();
		for (int i = 0, s = nodeList.size(); i < s; i++) {
			String key = nodeList.get(i).getKey();
			if(StringUtils.isBlank(key)){
				continue;
			}
			if (!nodeList.get(i).isLeaf()) {
				continue;
			}
			keyList.add(key);
			String desensitizationType = nodeList.get(i).getDesensitizationType();
			if(StringUtils.isNotBlank(desensitizationType)){//是否需要脱敏
				if(desensitizationTypeMap == null) {
					desensitizationTypeMap = new LinkedHashMap<String, String>();
				}
				desensitizationTypeMap.put(key, desensitizationType);
			}
			String cellFormat = nodeList.get(i).getCellFormat();
			if(StringUtils.isNotBlank(cellFormat)){//是否需要脱敏
				if(cellFormatMap == null) {
					cellFormatMap = new LinkedHashMap<String, String>();
				}
				cellFormatMap.put(key, cellFormat);
			}
		}
		return keyList;
	}

	/** 计算叶子数,即该节点所占的长度 */
	public int calLeavesAmount(TreeNode treeNode) {
		if (treeNode.isLeaf()) {
			treeNode.setLeafSize(1);
			return 1;
		}
		int sum = 0;
		for (TreeNode node : treeNode.childList) {
			sum += calLeavesAmount(node);
		}
		treeNode.setLeafSize(sum);
		return sum;
	}

	/** 填写所有节点的等级（层数） */
	public void calNodeLevel(TreeNode treeNode) {
		if (treeNode.parentNode == null) {
			treeNode.setLevel(-1);
		} else {
			treeNode.setLevel(treeNode.parentNode.getLevel() + 1);
		}
		if (!treeNode.isLeaf()) {
			for (TreeNode node : treeNode.getChildList()) {
				calNodeLevel(node);
			}
		}
	}

	/* 获取最大层数 */
	public int getMaxLevel() {
		List<TreeNode> list = this.getJuniors();
		int max = 0;
		for (TreeNode node : list) {
			int l = node.getLevel();
			max = max < l ? l : max;
		}
		return max;
	}

	public void print(String content) {
		System.out.println(content);
	}

	public void print(int content) {
		System.out.println(String.valueOf(content));
	}

	public void setChildList(List<TreeNode> childList) {
		this.childList = childList;
	}

	public int getParentId() {
		return parentId;
	}

	public void setParentId(int parentId) {
		this.parentId = parentId;
	}

	public int getSelfId() {
		return selfId;
	}

	public void setSelfId(int selfId) {
		this.selfId = selfId;
	}

	public TreeNode getParentNode() {
		return parentNode;
	}

	public void setParentNode(TreeNode parentNode) {
		this.parentNode = parentNode;
		this.setParentId(parentNode.getSelfId());
	}

	public String getNodeName() {
		return nodeName;
	}

	public void setNodeName(String nodeName) {
		this.nodeName = nodeName;
	}

	public int getLeafSize() {
		return leafSize;
	}

	public void setLeafSize(int leafSize) {
		this.leafSize = leafSize;
	}

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key != null ? key : "";
	}

	public int getLevel() {
		return level;
	}

	public void setLevel(int level) {
		this.level = level;
	}

	public int getColor() {
		return color;
	}

	public void setColor(int color) {
		this.color = color;
	}

	public String getDesensitizationType() {
		return desensitizationType;
	}

	public void setDesensitizationType(String desensitizationType) {
		this.desensitizationType = desensitizationType;
	}

	public Map<String, String> getDesensitizationTypeMap() {
		if(desensitizationTypeMap == null) {
			desensitizationTypeMap = new LinkedHashMap<String, String>();
		}
		return desensitizationTypeMap;
	}

	public String getCellFormat() {
		return cellFormat;
	}

	public TreeNode setCellFormat(String cellFormat) {
		this.cellFormat = cellFormat;
		return this;
	}

	public Map<String, String> getCellFormatMap() {
		if(cellFormatMap == null) {
			cellFormatMap = new LinkedHashMap<String, String>();
		}
		return cellFormatMap;
	}

	@Override
	public String toString() {
		String str = "TreeNode [parentId=" + parentId + ", selfId=" + selfId + ", nodeName=" + nodeName + ", leafSize="
				+ leafSize + ", color=" + color + ", key=" + key + ", level=" + level + ", \nchildList=";
		if (childList != null || !childList.isEmpty()) {
			for (Object obj : childList) {
				str += "\n" + obj.toString();
			}
		}else {
			str += "null";
		}
		str += "]";
		return str;
	}

}
