/*-
 * ~~~~~~licensing~~~~~~
 * objects-core
 * ==========
 * Copyright (C) 2020 - 2025 EmDev LLC
 * ==========
 * You may not use this file except in accordance with the License Terms of the Copyright
 * Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
 * rights to the Software and any copies are the property of the Copyright Holder. Unless
 * it is explicitly allowed the Copyright Holder, the User is prohibited from using the
 * Software for commercial purposes to provide services to third parties.
 * 
 * The Copyright Holder hereby declares that the Software is provided on an "AS IS".
 * Under no circumstances does the Copyright Holder guarantee or promise that the
 * Software provided by him will be suitable or not suitable for the specific purposes
 * of the User, that the Software will meet all commercial and personal subjective
 * expectations of the User, that the Software will work properly, without technical
 * errors, quickly and uninterruptedly.
 * 
 * Under no circumstances shall the Copyright Holder or its Affiliates is not liable
 * to the User for any direct or indirect losses of the User, his expenses or actual
 * damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
 * or damage to data, property, etc.
 * ~~~~~~/licensing~~~~~~
 */
package ru.entaxy.platform.base.objects.shell;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ru.entaxy.platform.base.support.CommonUtils;

// TODO move to base-support
public class SimpleObjectTree<T> {

	Map<String, SimpleObjectTreeNode<T>> allNodes = new HashMap<>();
	
	SimpleObjectTreeHelper<T> helper;
	
	SimpleObjectTreeNode<T> root;
	
	public SimpleObjectTree(SimpleObjectTreeHelper<T> helper) {
		this.helper = helper;
		this.root = helper.createNode("@root");
	}
	
	public void load(List<T> objects) {
		
		for (T object: objects) {
			SimpleObjectTreeNode<T> node = get(helper.getId(object));
			node.object = object;
			if (CommonUtils.isValid(helper.getParentId(object)))
				get(helper.getParentId(object)).addChild(node);
		}
		
	}
	
	public SimpleObjectTreeNode<T> get(String id) {
		if (!allNodes.containsKey(id)) {
			SimpleObjectTreeNode<T> node = helper.createNode(id);
			root.addChild(node);
			allNodes.put(id, node);
		}
		return allNodes.get(id);
	}
	

	public static class SimpleObjectTreeNode<T> {
		
		String id;
		T object;
		
		List<SimpleObjectTreeNode<T>> children = new ArrayList<>();
		
		SimpleObjectTreeNode<T> parent;
		
		public SimpleObjectTreeNode (String id) {
			this.id = id;
		}
		
		public void addChild(SimpleObjectTreeNode<T> child) {
			this.children.add(child);
			if (child.parent != null)
				child.parent.children.remove(child);
			child.parent = this;
		}
		
		public int getLevel() {
			if (parent == null)
				return 0;
			return parent.getLevel() + 1;
		}

		public String getId() {
			return id;
		}

		public T getObject() {
			return object;
		}
		
	}
	
	public static interface SimpleObjectTreeHelper<T> {
		
		String getId(T object);
		String getParentId(T object);
		
		SimpleObjectTreeNode<T> createNode(T object);
		SimpleObjectTreeNode<T> createNode(String id);
	}
	
	public static abstract class SimpleObjectTreeHelperCommon<T> implements SimpleObjectTreeHelper<T> {
		
		@Override
		public SimpleObjectTreeNode<T> createNode(String id) {
			SimpleObjectTreeNode<T> result = new SimpleObjectTreeNode<>(id); 
			return result;
		}

		@Override
		public SimpleObjectTreeNode<T> createNode(T object) {
			SimpleObjectTreeNode<T> result = new SimpleObjectTreeNode<>(getId(object));
			result.object = object;
			return result;
		}
		
	}  
}
