package net.ssehub.kernel_haven.variability_model;

import java.util.HashSet;
import java.util.Set;

import net.ssehub.kernel_haven.util.null_checks.NonNull;
import net.ssehub.kernel_haven.util.null_checks.Nullable;

/**
 * A {@link VariabilityVariable} that has additional information about the hierarchy of variables.
 * 
 * TODO: serialization
 * 
 * @author Adam
 */
public class HierarchicalVariable extends VariabilityVariable {

    private @Nullable HierarchicalVariable parent;
    
    private @NonNull Set<@NonNull HierarchicalVariable> children;
    
    private int nestingDepth;
    
    /**
     * Creates a {@link HierarchicalVariable}.
     * 
     * @param name The name of the variable.
     * @param type The type of the variable.
     */
    public HierarchicalVariable(@NonNull String name, @NonNull String type) {
        super(name, type);
        children = new HashSet<>();
    }

    /**
     * Creates a {@link HierarchicalVariable}.
     * 
     * @param name The name of the variable.
     * @param type The type of the variable.
     * @param dimacsNumer The number in the dimacs mapping of this variable.
     */
    public HierarchicalVariable(@NonNull String name, @NonNull String type, int dimacsNumer) {
        super(name, type, dimacsNumer);
        children = new HashSet<>();
    }
    
    /**
     * Returns the parent of this variable.
     * 
     * @return The parent variable. <code>null</code> if this variable has no parent.
     */
    public @Nullable HierarchicalVariable getParent() {
        return parent;
    }
    
    /**
     * Sets the parent for this variable, add this variable as a child to the parent variable and set the nesting depth
     * of this to parent+1. This method should only be called by the extractor that creates the variability model.
     * 
     * @param parent The new parent for this variable.
     */
    public void setParent(@Nullable HierarchicalVariable parent) {
        this.parent = parent;
        if (null != parent) {
            parent.children.add(this);
            this.nestingDepth = parent.nestingDepth + 1;
        }
    }
    
    /**
     * Returns the children of this variable. May be empty, if this has no children.
     * 
     * @return The children of this variable.
     */
    public @NonNull Set<@NonNull HierarchicalVariable> getChildren() {
        return children;
    }
    
    /**
     * Returns the nesting depth of this variable. This is the number of parents above this variable. 0 means top level.
     * 
     * @return The nesting depth of this variable.
     */
    public int getNestingDepth() {
        return nestingDepth;
    }
    
}

@@ -1568,24 +1568,35 @@
    %0A    /**%0A
+     * %3Cp%3E%0A
      * Sets 
@@ -1730,16 +1730,229 @@
 arent+1.
+ If there was a previous parent set for this, then this variable is removed from the%0A     * previous parents children list. If the new parent is null, then the new nesting depth is 0.%0A     * %3C/p%3E%0A     * %3Cp%3E%0A     *
  This me
@@ -2027,24 +2027,36 @@
 lity model.%0A
+     * %3C/p%3E%0A
      * %0A    
@@ -2173,32 +2173,252 @@
 iable parent) %7B%0A
+        // remove from previous%0A        HierarchicalVariable previousParent = this.parent;%0A        if (previousParent != null) %7B%0A            previousParent.children.remove(this);%0A        %7D%0A        %0A        // add to new%0A
         this.par
@@ -2557,16 +2557,68 @@
 th + 1;%0A
+        %7D else %7B%0A            this.nestingDepth = 0;%0A
         

Handle more cases in HierarchicalVariable.setParent