//Generic class that mimics the scene system in the Godot engine.
//Every object used in this project will inherit this class, which allows them
//to interact with each other in a fluid way based on Godot's node tree system.
//Imported from my JavaGame project.
abstract public class Scene {
  
  private String name = "Scene";
  private ArrayList<Scene> children = new ArrayList<Scene>();
  private Scene parent;
  private boolean visible = true;
  
  public Scene() {
  }
  
  public Scene(boolean vis) {
    visible = vis;
  }
  
  public Scene(String n) {
    name = n;
  }
  
  //Called each time a scene becomes visible.
  //Meant to be overwritten by the child class.
  public void ready() {
  }
  
  //Called every frame as long as the scene is visible.
  //Meant to be overwritten by the child class.
  public void process() {
  }
  
  //Function that allows the process function to work.
  final public void _process() {
    if (visible) {
      process();
      for (Scene s : getChildren()) {
        s._process();
      }
    }
  }
  
  //Returns the array of scenes that are children of this scene.
  public ArrayList<Scene> getChildren() {
    return children;
  }
  
  //Returns a single child scene based on its index.
  public Scene getChild(int index) {
    return children.get(index);
  }
  
  //Adds an additional child scene and returns said scene.
  public Scene addChild(Scene child) {
    child.setParent(this);
    children.add(child);
    return child;
  }
  
  //Traverses the scene tree starting with this scene
  //and returns the first instance of a scene with the 
  //desired name, or null if it doesn't exist.
  public Scene findChild(String nam) {
    Scene s = null;
    int i = 0;
    while (i < getChildren().size() && s == null) {
      if (getChild(i).getName() == nam) {
        s = getChild(i);
      }
      i++;
    }
    return s;
  }
  
  //Removes and returns a child scene based on its index.
  public Scene removeChild(int index) {
    getChild(index).setParent(null);
    return children.remove(index);
  }
  
  //Returns the parent scene of this scene.
  //To access the parent scene's functions, you must
  //convert it to its specific subclass first.
  public Scene getParent() {
    return parent;
  }
  
  //Sets this scene's parent to a new parent scene.
  public void setParent(Scene p) {
    parent = p;
  }
  
  public boolean getVis() {
    return visible;
  }
  
  public void setVis(boolean v) {
    visible = v;
    if (v) ready();
    for (Scene s : getChildren()) {
      s.setVis(v);
    }
  }
  
  public String getName() {
    return name;
  }
  
  //Returns the scene so that you can declare the name of a scene when created without a constructor and set it to a child all in one line.
  public Scene setName(String n) {
    name = n;
    return this;
  }
  
}
