package util.sqlparse.visitor.spark.visitor;

import com.alibaba.druid.sql.ast.SQLDataType;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLAlterIndexStatement;
import com.alibaba.druid.sql.ast.statement.SQLAlterTableAddIndex;
import com.alibaba.druid.sql.ast.statement.SQLCheck;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLLateralViewTableSource;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery;
import com.alibaba.druid.sql.ast.statement.SQLUnionQueryTableSource;
import com.alibaba.druid.sql.ast.statement.SQLWithSubqueryClause;
import com.alibaba.druid.sql.dialect.spark.ast.expr.HiveRowFormat;
import com.alibaba.druid.sql.dialect.spark.ast.expr.SparkColumnDef;
import com.alibaba.druid.sql.dialect.spark.ast.expr.SparkColumnSpecExpr;
import com.alibaba.druid.sql.dialect.spark.ast.expr.SparkDateExpr;
import com.alibaba.druid.sql.dialect.spark.ast.expr.SparkDefProperty;
import com.alibaba.druid.sql.dialect.spark.ast.expr.SparkIntervalExpr;
import com.alibaba.druid.sql.dialect.spark.ast.expr.SparkNullsExpr;
import com.alibaba.druid.sql.dialect.spark.ast.expr.SparkNumberExpr;
import com.alibaba.druid.sql.dialect.spark.ast.expr.SparkSQLSubqueryTableSource;
import com.alibaba.druid.sql.dialect.spark.ast.expr.SparkSampleExpr;
import com.alibaba.druid.sql.dialect.spark.ast.expr.SparkSelectJoinTableSource;
import com.alibaba.druid.sql.dialect.spark.ast.expr.SparkSelectPivot;
import com.alibaba.druid.sql.dialect.spark.ast.expr.SparkSelectTableReference;
import com.alibaba.druid.sql.dialect.spark.ast.expr.SparkTablePartition;
import com.alibaba.druid.sql.dialect.spark.ast.expr.SparkTransformExpr;
import com.alibaba.druid.sql.dialect.spark.ast.expr.SparkValuesExpr;
import com.alibaba.druid.sql.dialect.spark.ast.expr.SparkWithExpr;
import com.alibaba.druid.sql.dialect.spark.ast.statement.SparkAlterDatabaseStatement;
import com.alibaba.druid.sql.dialect.spark.ast.statement.SparkAlterTableStatement;
import com.alibaba.druid.sql.dialect.spark.ast.statement.SparkAlterViewStatement;
import com.alibaba.druid.sql.dialect.spark.ast.statement.SparkCacheTableStatement;
import com.alibaba.druid.sql.dialect.spark.ast.statement.SparkCreateDatabaseStatement;
import com.alibaba.druid.sql.dialect.spark.ast.statement.SparkCreateTableStatement;
import com.alibaba.druid.sql.dialect.spark.ast.statement.SparkInsertStatement;
import com.alibaba.druid.sql.dialect.spark.ast.statement.SparkLoadStatement;
import com.alibaba.druid.sql.dialect.spark.ast.statement.SparkRefreshStatement;
import com.alibaba.druid.sql.dialect.spark.ast.statement.SparkShowTableStatement;
import com.alibaba.druid.sql.dialect.spark.visitor.DefaultSparkVisitor;
import java.util.List;
import util.sqlparse.visitor.common.scope.Scope;

public abstract class ParseVisitor extends DefaultSparkVisitor {
   private boolean debug = false;
   protected Scope scope;

   public ParseVisitor(Scope scope) {
      this.scope = scope;
   }

   public void perform(List<SQLStatement> statements) {
      if (statements != null && statements.size() != 0) {
         for(SQLStatement statement : statements) {
            statement.accept(this);
         }

         this.scope.reset();
      }
   }

   public boolean visit(SQLSelectStatement x) {
      if (this.debug) {
         System.out.println("enter SQLSelectStatement" + x.toString());
      }

      this.scope.enterScope((SQLObject)x);
      return true;
   }

   public void endVisit(SQLSelectStatement x) {
      if (this.debug) {
         System.out.println("exit SQLSelectStatement" + x.toString());
      }

      this.scope.exitScope();
   }

   public boolean visit(SparkInsertStatement x) {
      this.scope.enterScope((SQLObject)x);
      return true;
   }

   public void endVisit(SparkInsertStatement x) {
      this.scope.exitScope();
   }

   public boolean visit(SparkInsertStatement.SparkFormat x) {
      return true;
   }

   public void endVisit(SparkInsertStatement.SparkFormat x) {
   }

   public boolean visit(SparkLoadStatement x) {
      this.scope.enterScope((SQLObject)x);
      return true;
   }

   public void endVisit(SparkLoadStatement x) {
      this.scope.exitScope();
   }

   public boolean visit(SparkSampleExpr x) {
      return true;
   }

   public void endVisit(SparkSampleExpr x) {
   }

   public boolean visit(SparkIntervalExpr x) {
      return true;
   }

   public void endVisit(SparkIntervalExpr x) {
   }

   public boolean visit(SparkIntervalExpr.SparkIntervalItem x) {
      return true;
   }

   public void endVisit(SparkIntervalExpr.SparkIntervalItem x) {
   }

   public boolean visit(SparkNumberExpr x) {
      return true;
   }

   public void endVisit(SparkNumberExpr x) {
   }

   public boolean visit(SparkAlterDatabaseStatement x) {
      return false;
   }

   public void endVisit(SparkAlterDatabaseStatement x) {
   }

   public boolean visit(SparkAlterTableStatement x) {
      this.scope.enterScope((SQLObject)x);
      return true;
   }

   public void endVisit(SparkAlterTableStatement x) {
      this.scope.exitScope();
   }

   public boolean visit(SparkAlterTableStatement.SparkAlterTableReNameTo x) {
      return false;
   }

   public void endVisit(SparkAlterTableStatement.SparkAlterTableReNameTo x) {
   }

   public boolean visit(SparkAlterTableStatement.SparkAlterTableAddColumns x) {
      return false;
   }

   public void endVisit(SparkAlterTableStatement.SparkAlterTableAddColumns x) {
   }

   public boolean visit(SparkAlterTableStatement.SparkAlterTableDropColumns x) {
      return false;
   }

   public void endVisit(SparkAlterTableStatement.SparkAlterTableDropColumns x) {
   }

   public boolean visit(SparkAlterTableStatement.SparkAlterTableRenameColumn x) {
      return false;
   }

   public void endVisit(SparkAlterTableStatement.SparkAlterTableRenameColumn x) {
   }

   public boolean visit(SparkAlterTableStatement.SparkAlterTableChangeColumn x) {
      return false;
   }

   public void endVisit(SparkAlterTableStatement.SparkAlterTableChangeColumn x) {
   }

   public boolean visit(SparkAlterTableStatement.SparkAlterTableReplaceColumns x) {
      return false;
   }

   public void endVisit(SparkAlterTableStatement.SparkAlterTableReplaceColumns x) {
   }

   public boolean visit(SparkAlterTableStatement.SparkAlterTableAddOrDropPartition x) {
      return false;
   }

   public void endVisit(SparkAlterTableStatement.SparkAlterTableAddOrDropPartition x) {
   }

   public boolean visit(SparkAlterTableStatement.SparkAlterTableSetUnsetProps x) {
      return false;
   }

   public void endVisit(SparkAlterTableStatement.SparkAlterTableSetUnsetProps x) {
   }

   public boolean visit(SparkAlterViewStatement x) {
      this.scope.enterScope((SQLObject)x);
      return true;
   }

   public void endVisit(SparkAlterViewStatement x) {
      this.scope.exitScope();
   }

   public boolean visit(SparkAlterViewStatement.SparkAlterViewReNameTo x) {
      return false;
   }

   public void endVisit(SparkAlterViewStatement.SparkAlterViewReNameTo x) {
   }

   public boolean visit(SparkAlterViewStatement.SparkAlterViewSetUnsetProps x) {
      return false;
   }

   public void endVisit(SparkAlterViewStatement.SparkAlterViewSetUnsetProps x) {
   }

   public boolean visit(SparkColumnSpecExpr x) {
      return false;
   }

   public void endVisit(SparkColumnSpecExpr x) {
   }

   public boolean visit(SparkCreateDatabaseStatement x) {
      return false;
   }

   public void endVisit(SparkCreateDatabaseStatement x) {
   }

   public boolean visit(SparkCacheTableStatement x) {
      return false;
   }

   public void endVisit(SparkCacheTableStatement x) {
   }

   public boolean visit(SparkCacheTableStatement.SparkCacheTableStatementQuery x) {
      return false;
   }

   public void endVisit(SparkCacheTableStatement.SparkCacheTableStatementQuery x) {
   }

   public boolean visit(SQLWithSubqueryClause x) {
      if (this.debug) {
         System.out.println("enter SQLWithSubqueryClause" + x.toString());
      }

      this.scope.enterScope((SQLObject)x);
      return true;
   }

   public void endVisit(SQLWithSubqueryClause x) {
      if (this.debug) {
         System.out.println("exit SQLWithSubqueryClause" + x.toString());
      }

      this.scope.exitScope();
   }

   public boolean visit(SQLWithSubqueryClause.Entry x) {
      if (this.debug) {
         System.out.println("enter SQLWithSubqueryClause.Entry" + x.toString());
      }

      this.scope.enterScope((SQLObject)x);
      return true;
   }

   public void endVisit(SQLWithSubqueryClause.Entry x) {
      if (this.debug) {
         System.out.println("exit SQLWithSubqueryClause.Entry" + x.toString());
      }

      this.scope.exitScope();
   }

   public boolean visit(SQLSelectQueryBlock x) {
      if (this.debug) {
         System.out.println("enter SQLSelectQueryBlock " + x.toString());
      }

      this.scope.enterScope((SQLObject)x);
      return true;
   }

   public void endVisit(SQLSelectQueryBlock x) {
      if (this.debug) {
         System.out.println("exit SQLSelectQueryBlock " + x.toString());
      }

      this.scope.exitScope();
   }

   public boolean visit(SQLUnionQuery x) {
      this.scope.enterScope((SQLObject)x);
      return true;
   }

   public void endVisit(SQLUnionQuery x) {
      this.scope.exitScope();
   }

   public boolean visit(SQLLateralViewTableSource x) {
      this.scope.enterScope((SQLObject)x);
      return true;
   }

   public void endVisit(SQLLateralViewTableSource x) {
      this.scope.exitScope();
   }

   public boolean visit(SparkCreateTableStatement x) {
      return true;
   }

   public void endVisit(SparkCreateTableStatement x) {
   }

   public boolean visit(SparkWithExpr x) {
      return true;
   }

   public void endVisit(SparkWithExpr x) {
   }

   public boolean visit(SparkValuesExpr x) {
      return true;
   }

   public void endVisit(SparkValuesExpr x) {
   }

   public boolean visit(SparkSelectPivot x) {
      return true;
   }

   public void endVisit(SparkSelectPivot x) {
   }

   public boolean visit(SparkSelectPivot.Item x) {
      return true;
   }

   public void endVisit(SparkSelectPivot.Item x) {
   }

   public boolean visit(SparkSQLSubqueryTableSource x) {
      if (this.debug) {
         System.out.println("enter SQLSubqueryTableSource" + x.toString());
      }

      this.scope.enterScope((SQLObject)x);
      return true;
   }

   public void endVisit(SparkSQLSubqueryTableSource x) {
      if (this.debug) {
         System.out.println("exit SQLSubqueryTableSource" + x.toString());
      }

      for(Scope s : this.scope.getCurrent().getChildren()) {
         s.isolated = false;
      }

      this.scope.exitScope();
   }

   public boolean visit(SparkSelectJoinTableSource x) {
      return true;
   }

   public void endVisit(SparkSelectJoinTableSource x) {
   }

   public boolean visit(SQLUnionQueryTableSource x) {
      if (this.debug) {
         System.out.println("enter SQLUnionQueryTableSource" + x.toString());
      }

      this.scope.enterScope((SQLObject)x);
      return true;
   }

   public void endVisit(SQLUnionQueryTableSource x) {
      if (this.debug) {
         System.out.println("exit SQLUnionQueryTableSource" + x.toString());
      }

      for(Scope s1 : this.scope.getChildren()) {
         s1.isolated = false;
      }

      this.scope.exitScope();
   }

   public boolean visit(SQLExprTableSource x) {
      return true;
   }

   public void endVisit(SQLExprTableSource x) {
   }

   public boolean visit(SparkSelectTableReference x) {
      return true;
   }

   public void endVisit(SparkSelectTableReference x) {
   }

   public boolean visit(SparkNullsExpr x) {
      return true;
   }

   public void endVisit(SparkNullsExpr x) {
   }

   public boolean visit(SparkDefProperty x) {
      return true;
   }

   public void endVisit(SparkDefProperty x) {
   }

   public boolean visit(SparkColumnDef x) {
      return true;
   }

   public void endVisit(SparkColumnDef x) {
   }

   public boolean visit(SparkTransformExpr x) {
      return true;
   }

   public void endVisit(SparkTransformExpr x) {
   }

   public boolean visit(SparkTransformExpr.CommandScriptDef x) {
      return true;
   }

   public void endVisit(SparkTransformExpr.CommandScriptDef x) {
   }

   public boolean visit(HiveRowFormat x) {
      return true;
   }

   public void endVisit(HiveRowFormat x) {
   }

   public boolean visit(HiveRowFormat.RowFormatDelimitor x) {
      return true;
   }

   public void endVisit(HiveRowFormat.RowFormatDelimitor x) {
   }

   public boolean visit(HiveRowFormat.RowFormatSede x) {
      return true;
   }

   public void endVisit(HiveRowFormat.RowFormatSede x) {
   }

   public boolean visit(SparkTablePartition x) {
      return true;
   }

   public void endVisit(SparkTablePartition x) {
   }

   public boolean visit(SparkDateExpr x) {
      return true;
   }

   public void endVisit(SparkDateExpr x) {
   }

   public boolean visit(SparkRefreshStatement x) {
      return true;
   }

   public void endVisit(SparkRefreshStatement x) {
   }

   protected void visitChild(SQLObject x) {
      if (x != null) {
         x.accept(this);
      }
   }

   protected void visitChild(List<? extends SQLObject> x) {
      if (x != null && x.size() != 0) {
         for(SQLObject sqlObject : x) {
            this.visitChild(sqlObject);
         }

      }
   }

   public boolean isParentTypeRecursive(SQLObject parent) {
      if (null != parent) {
         return !(parent instanceof SQLDataType) && !(parent instanceof SQLCheck) && !(parent instanceof SQLColumnDefinition) && !(parent instanceof SQLCreateIndexStatement) && !(parent instanceof SQLAlterIndexStatement) && !(parent instanceof SQLAlterTableAddIndex) ? this.isParentTypeRecursive(parent.getParent()) : true;
      } else {
         return false;
      }
   }

   public boolean visit(SparkShowTableStatement x) {
      return false;
   }

   public void endVisit(SparkShowTableStatement x) {
   }

   protected boolean isEqual(String name1, String name2) {
      return this.scope.dialector.isEqual(name1, name2);
   }
}
