package com.chenyang.druid.sql.ast.statement;

import com.chenyang.druid.sql.ast.SQLExpr;
import com.chenyang.druid.sql.ast.SQLName;
import com.chenyang.druid.sql.ast.SQLObjectImpl;
import com.chenyang.druid.sql.ast.SQLReplaceable;
import com.chenyang.druid.sql.ast.SQLStatement;
import com.chenyang.druid.sql.visitor.SQLASTVisitor;
import java.util.ArrayList;
import java.util.List;

public class SQLWithSubqueryClause extends SQLObjectImpl {
   private Boolean recursive;
   private final List<Entry> entries = new ArrayList();

   public SQLWithSubqueryClause clone() {
      SQLWithSubqueryClause x = new SQLWithSubqueryClause();
      x.recursive = this.recursive;

      for(Entry entry : this.entries) {
         Entry entry2 = entry.clone();
         entry2.setParent(x);
         x.entries.add(entry2);
      }

      return x;
   }

   public List<Entry> getEntries() {
      return this.entries;
   }

   public void addEntry(Entry entry) {
      if (entry != null) {
         entry.setParent(this);
      }

      this.entries.add(entry);
   }

   public Boolean getRecursive() {
      return this.recursive;
   }

   public void setRecursive(Boolean recursive) {
      this.recursive = recursive;
   }

   protected void accept0(SQLASTVisitor visitor) {
      if (visitor.visit(this)) {
         for(int i = 0; i < this.entries.size(); ++i) {
            Entry entry = (Entry)this.entries.get(i);
            if (entry != null) {
               entry.accept(visitor);
            }
         }
      }

      visitor.endVisit(this);
   }

   public Entry findEntry(long alias_hash) {
      if (alias_hash == 0L) {
         return null;
      } else {
         for(Entry entry : this.entries) {
            if (entry.aliasHashCode64() == alias_hash) {
               return entry;
            }
         }

         return null;
      }
   }

   public boolean equals(Object o) {
      if (this == o) {
         return true;
      } else if (o != null && this.getClass() == o.getClass()) {
         SQLWithSubqueryClause that = (SQLWithSubqueryClause)o;
         if (this.recursive != null) {
            if (!this.recursive.equals(that.recursive)) {
               return false;
            }
         } else if (that.recursive != null) {
            return false;
         }

         return this.entries.equals(that.entries);
      } else {
         return false;
      }
   }

   public int hashCode() {
      int result = this.recursive != null ? this.recursive.hashCode() : 0;
      result = 31 * result + this.entries.hashCode();
      return result;
   }

   public static class Entry extends SQLTableSourceImpl implements SQLReplaceable {
      protected final List<SQLName> columns = new ArrayList();
      protected SQLSelect subQuery;
      protected SQLStatement returningStatement;
      protected SQLExpr expr;

      public Entry() {
      }

      public Entry(String alias, SQLSelect select) {
         this.setAlias(alias);
         this.setSubQuery(select);
      }

      public Entry(String alias, SQLExpr expr) {
         this.setAlias(alias);
         this.setExpr(expr);
      }

      public void cloneTo(Entry x) {
         for(SQLName column : this.columns) {
            SQLName column2 = column.clone();
            column2.setParent(x);
            x.columns.add(column2);
         }

         if (this.subQuery != null) {
            x.setSubQuery(this.subQuery.clone());
         }

         if (this.returningStatement != null) {
            this.setReturningStatement(this.returningStatement.clone());
         }

         x.alias = this.alias;
         x.expr = this.expr;
      }

      public boolean replace(SQLExpr expr, SQLExpr target) {
         if (this.flashback == expr) {
            this.setFlashback(target);
            return true;
         } else {
            for(int i = 0; i < this.columns.size(); ++i) {
               if (this.columns.get(i) == expr) {
                  target.setParent(this);
                  this.columns.set(i, (SQLName)expr);
                  return true;
               }
            }

            return false;
         }
      }

      public Entry clone() {
         Entry x = new Entry();
         this.cloneTo(x);
         return x;
      }

      public SQLExpr getExpr() {
         return this.expr;
      }

      public void setExpr(SQLExpr expr) {
         this.expr = expr;
      }

      protected void accept0(SQLASTVisitor visitor) {
         if (visitor.visit(this)) {
            for(int i = 0; i < this.columns.size(); ++i) {
               SQLExpr column = (SQLExpr)this.columns.get(i);
               if (column != null) {
                  column.accept(visitor);
               }
            }

            if (this.subQuery != null) {
               this.subQuery.accept(visitor);
            }

            if (this.returningStatement != null) {
               this.returningStatement.accept(visitor);
            }

            if (this.expr != null) {
               this.expr.accept(visitor);
            }
         }

         visitor.endVisit(this);
      }

      public SQLSelect getSubQuery() {
         return this.subQuery;
      }

      public void setSubQuery(SQLSelect subQuery) {
         if (subQuery != null) {
            subQuery.setParent(this);
         }

         this.subQuery = subQuery;
      }

      public SQLStatement getReturningStatement() {
         return this.returningStatement;
      }

      public void setReturningStatement(SQLStatement returningStatement) {
         if (returningStatement != null) {
            returningStatement.setParent(this);
         }

         this.returningStatement = returningStatement;
      }

      public List<SQLName> getColumns() {
         return this.columns;
      }

      public SQLTableSource findTableSourceWithColumn(long columnNameHash, String columnName, int option) {
         for(SQLName column : this.columns) {
            if (column.nameHashCode64() == columnNameHash) {
               return this;
            }
         }

         if (this.subQuery != null) {
            SQLSelectQueryBlock queryBlock = this.subQuery.getFirstQueryBlock();
            if (queryBlock != null && queryBlock.findSelectItem(columnNameHash) != null) {
               return this;
            }
         }

         return null;
      }

      public boolean equals(Object o) {
         if (this == o) {
            return true;
         } else if (o != null && this.getClass() == o.getClass()) {
            if (!super.equals(o)) {
               return false;
            } else {
               Entry entry = (Entry)o;
               if (!this.columns.equals(entry.columns)) {
                  return false;
               } else {
                  if (this.subQuery != null) {
                     if (!this.subQuery.equals(entry.subQuery)) {
                        return false;
                     }
                  } else if (entry.subQuery != null) {
                     return false;
                  }

                  return this.returningStatement != null ? this.returningStatement.equals(entry.returningStatement) : entry.returningStatement == null;
               }
            }
         } else {
            return false;
         }
      }

      public int hashCode() {
         int result = super.hashCode();
         result = 31 * result + (this.columns != null ? this.columns.hashCode() : 0);
         result = 31 * result + (this.subQuery != null ? this.subQuery.hashCode() : 0);
         result = 31 * result + (this.returningStatement != null ? this.returningStatement.hashCode() : 0);
         return result;
      }
   }
}
