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

import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLObjectImpl;
import com.alibaba.druid.sql.ast.SQLReplaceable;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import java.util.ArrayList;
import java.util.List;

public class SQLSelectGroupByClause extends SQLObjectImpl implements SQLReplaceable {
   private final List<SQLExpr> items = new ArrayList();
   private SQLExpr having;
   private boolean withRollUp = false;
   private boolean withCube = false;
   private boolean distinct = false;
   private boolean paren = false;
   private boolean all = false;

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

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

      visitor.endVisit(this);
   }

   public boolean isDistinct() {
      return this.distinct;
   }

   public void setDistinct(boolean distinct) {
      this.distinct = distinct;
   }

   public boolean isWithRollUp() {
      return this.withRollUp;
   }

   public void setWithRollUp(boolean withRollUp) {
      this.withRollUp = withRollUp;
   }

   public boolean isWithCube() {
      return this.withCube;
   }

   public void setWithCube(boolean withCube) {
      this.withCube = withCube;
   }

   public SQLExpr getHaving() {
      return this.having;
   }

   public void setHaving(SQLExpr having) {
      if (having != null) {
         having.setParent(this);
      }

      this.having = having;
   }

   public void addHaving(SQLExpr condition) {
      if (condition != null) {
         if (this.having == null) {
            this.having = condition;
         } else {
            this.having = SQLBinaryOpExpr.and(this.having, condition);
         }

      }
   }

   public List<SQLExpr> getItems() {
      return this.items;
   }

   public boolean containsItem(SQLExpr item) {
      return this.items.contains(item);
   }

   public void addItem(SQLExpr sqlExpr) {
      if (sqlExpr != null) {
         sqlExpr.setParent(this);
         this.items.add(sqlExpr);
      }

   }

   public void addItem(int index, SQLExpr sqlExpr) {
      if (sqlExpr != null) {
         sqlExpr.setParent(this);
         this.items.add(index, sqlExpr);
      }

   }

   public SQLSelectGroupByClause clone() {
      SQLSelectGroupByClause x = new SQLSelectGroupByClause();

      for(SQLExpr item : this.items) {
         SQLExpr item2 = item.clone();
         item2.setParent(x);
         x.items.add(item2);
      }

      if (this.having != null) {
         x.setHaving(this.having.clone());
      }

      x.withRollUp = this.withRollUp;
      x.withCube = this.withCube;
      x.distinct = this.distinct;
      x.paren = this.paren;
      if (this.hint != null) {
         x.setHint(this.hint.clone());
      }

      return x;
   }

   public boolean replace(SQLExpr expr, SQLExpr target) {
      if (expr == this.having) {
         this.setHaving(target);
         return true;
      } else {
         for(int i = this.items.size() - 1; i >= 0; --i) {
            if (this.items.get(i) == expr) {
               if (target instanceof SQLIntegerExpr) {
                  this.items.remove(i);
               } else {
                  this.items.set(i, target);
               }

               return true;
            }
         }

         return false;
      }
   }

   public SQLCommentHint getHint() {
      return this.hint;
   }

   public void setHint(SQLCommentHint hint) {
      this.hint = hint;
   }

   public boolean isParen() {
      return this.paren;
   }

   public void setParen(boolean paren) {
      this.paren = paren;
   }

   public boolean equals(Object o) {
      if (this == o) {
         return true;
      } else if (o != null && this.getClass() == o.getClass()) {
         SQLSelectGroupByClause that = (SQLSelectGroupByClause)o;
         if (this.withRollUp != that.withRollUp) {
            return false;
         } else if (this.withCube != that.withCube) {
            return false;
         } else if (this.distinct != that.distinct) {
            return false;
         } else if (this.paren != that.paren) {
            return false;
         } else {
            if (this.items != null) {
               if (!this.items.equals(that.items)) {
                  return false;
               }
            } else if (that.items != null) {
               return false;
            }

            if (this.having != null) {
               if (!this.having.equals(that.having)) {
                  return false;
               }
            } else if (that.having != null) {
               return false;
            }

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

   public int hashCode() {
      int result = this.items != null ? this.items.hashCode() : 0;
      result = 31 * result + (this.having != null ? this.having.hashCode() : 0);
      result = 31 * result + (this.withRollUp ? 1 : 0);
      result = 31 * result + (this.withCube ? 1 : 0);
      result = 31 * result + (this.distinct ? 1 : 0);
      result = 31 * result + (this.paren ? 1 : 0);
      result = 31 * result + (this.hint != null ? this.hint.hashCode() : 0);
      return result;
   }

   public boolean isAll() {
      return this.all;
   }

   public void setAll(boolean all) {
      this.all = all;
   }
}
