package inference.rewrite;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.Getter;
import models.terms.DependencyTerm;
import models.terms.EvaluatableTerm;
import models.terms.Resource;
public class ResourceTree {
@Getter
private Resource root;
private Map<Position, List<Position>> tree;
private Map<Position, Resource> resourceMap;
public ResourceTree(EvaluatableTerm term) {
tree = new HashMap<>();
resourceMap = new HashMap<>();
constructResourceTree(term, new Position(List.of(0)));
root = resourceMap.get(new Position(List.of(0)));
}
private List<Position> constructResourceTree(EvaluatableTerm term, Position top) {
if (term instanceof Resource resource) {
resourceMap.put(top, resource);
return List.of(top);
} else if (term instanceof DependencyTerm depTerm) {
EvaluatableTerm dependingTerm = depTerm.getDependingTerm();
List<Resource> dependedResources = depTerm.getDependedResources();
List<EvaluatableTerm> argumentTerms = depTerm.getArgumentTerms();
List<Position> dependingTermPositions = constructResourceTree(dependingTerm, top);
List<Position> resultPositions = new ArrayList<>();
for (Position pos: dependingTermPositions) {
tree.put(pos, new ArrayList<>());
}
for (int i = 0; i < dependedResources.size(); i++) {
for (Position pos : dependingTermPositions) {
Position nextPos = pos.addPath(i);
tree.get(pos).add(nextPos);
Position dependedResourcePosition= constructResourceTree(dependedResources.get(i), nextPos).get(0);
tree.put(dependedResourcePosition, new ArrayList<>());
Position argumentTermPosition = dependedResourcePosition.addPath(0);
tree.get(dependedResourcePosition).add(argumentTermPosition);
tree.put(argumentTermPosition, new ArrayList<>());
resultPositions.addAll(constructResourceTree(argumentTerms.get(i), argumentTermPosition));
}
}
return resultPositions;
} else {
return null;
}
}
@Override
public String toString() {
return tree.toString();
}
public void debug(Position pos) {
System.out.println(pos + ", " + resourceMap.get(pos));
if (tree.containsKey(pos)) {
for (Position nextPos : tree.get(pos)) {
debug(nextPos);
}
}
}
public void debugAllPath() {
debugAllPath(new Position(), new ArrayList<>());
}
private void debugAllPath(Position pos, List<Resource> curPath) {
curPath.add(resourceMap.get(pos));
if (tree.get(pos).size() == 0) {
System.out.println(curPath.stream().map(Resource::toString).collect(Collectors.joining("-")));
} else {
for (Position nextPos: tree.get(pos)) {
debugAllPath(nextPos, curPath);
}
}
curPath.remove(curPath.size() - 1);
}
}