package util.sqlparse.visitor.es.visitor;

import com.alibaba.druid.sql.ast.SQLObject;
import org.antlr.v4.runtime.tree.ParseTree;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import util.sqlparse.visitor.common.Context;
import util.sqlparse.visitor.common.ID;
import util.sqlparse.visitor.es.api.Request;

public class Scope extends ID {
   public Context context;
   protected Scope current;
   public Scope parent;
   public ParseTree ref;
   protected List<Scope> children;
   private boolean debug = false;
   private Set<String> indices;
   private Set<String> mappings;
   private Set<String> fields;
   public Request request;

   public Scope(ParseTree tree) {
      this.ref = tree;
      this.indices = new HashSet();
      this.mappings = new HashSet();
      this.fields = new HashSet();
      this.current = this;
      this.children = new ArrayList();
   }

   public void enterScope(Scope scope) {
      this.current.append(scope);
      if (this.debug) {
         System.out.println("[E]" + this.current.id + "->" + scope.id + "     " + scope.ref.getClass().toString() + "\n     " + scope.ref);
      }

      this.current = scope;
   }

   public void reset() {
      this.current = this;
   }

   public void enterScope(ParseTree parseTree) {
      for(Scope child : this.current.children) {
         if (child.ref.equals(parseTree)) {
            if (this.debug) {
               System.out.println("[E]" + this.current.id + "->" + child.id + "     " + child.ref.getClass().toString() + "\n     " + child.ref);
            }

            this.current = child;
            return;
         }
      }

   }

   public Scope getScope(SQLObject sqlObject) {
      for(Scope child : this.current.children) {
         if (child.ref.equals(sqlObject)) {
            return child;
         }
      }

      return null;
   }

   public void exitScope() {
      if (this.debug) {
         if (this.current.parent != null) {
            System.out.println("[X]" + this.current.id + "->" + this.current.parent.id + "     " + this.current.ref.getClass().toString());
         } else {
            System.out.println("[X]" + this.current.id + "->root");
         }
      }

      this.current = this.current.parent;
      if (this.current == null) {
         this.current = this;
      }

   }

   private void append(Scope child) {
      this.children.add(child);
      child.context = this.context;
      child.parent = this.current;
   }

   public Scope getCurrent() {
      return this.current;
   }

   public void addField(String field) {
      this.fields.add(field);
   }

   public void addFields(List<String> field) {
      this.fields.addAll(field);
   }

   public void addIndex(String index) {
      this.indices.add(index);
   }

   public void addMapping(String mapping) {
      this.mappings.add(mapping);
   }
}
