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

import com.chenyang.druid.DbType;
import com.chenyang.druid.sql.SQLUtils;
import com.chenyang.druid.sql.ast.SQLDataType;
import com.chenyang.druid.sql.ast.SQLExpr;
import com.chenyang.druid.sql.ast.SQLExprImpl;
import com.chenyang.druid.sql.ast.SQLObject;
import com.chenyang.druid.sql.ast.SQLObjectImpl;
import com.chenyang.druid.sql.ast.SQLReplaceable;
import com.chenyang.druid.sql.visitor.SQLASTVisitor;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class SQLCaseExpr extends SQLExprImpl implements SQLReplaceable, Serializable {
   private static final long serialVersionUID = 1L;
   private final List<Item> items = new ArrayList();
   private SQLExpr valueExpr;
   private SQLExpr elseExpr;

   public SQLExpr getValueExpr() {
      return this.valueExpr;
   }

   public void setValueExpr(SQLExpr valueExpr) {
      if (valueExpr != null) {
         valueExpr.setParent(this);
      }

      this.valueExpr = valueExpr;
   }

   public SQLExpr getElseExpr() {
      return this.elseExpr;
   }

   public void setElseExpr(SQLExpr elseExpr) {
      if (elseExpr != null) {
         elseExpr.setParent(this);
      }

      this.elseExpr = elseExpr;
   }

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

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

   }

   public void addItem(SQLExpr condition, SQLExpr value) {
      this.addItem(new Item(condition, value));
   }

   protected void accept0(SQLASTVisitor visitor) {
      if (visitor.visit(this)) {
         if (this.valueExpr != null) {
            this.valueExpr.accept(visitor);
         }

         for(Item item : this.items) {
            if (item != null) {
               item.accept(visitor);
            }
         }

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

      visitor.endVisit(this);
   }

   public List getChildren() {
      List<SQLObject> children = new ArrayList();
      if (this.valueExpr != null) {
         children.add(this.valueExpr);
      }

      children.addAll(this.items);
      if (this.elseExpr != null) {
         children.add(this.elseExpr);
      }

      return children;
   }

   public boolean replace(SQLExpr expr, SQLExpr target) {
      if (this.valueExpr == expr) {
         this.setValueExpr(target);
         return true;
      } else if (this.elseExpr == expr) {
         this.setElseExpr(target);
         return true;
      } else {
         return false;
      }
   }

   public int hashCode() {
      int prime = 31;
      int result = 1;
      result = 31 * result + (this.elseExpr == null ? 0 : this.elseExpr.hashCode());
      result = 31 * result + this.items.hashCode();
      result = 31 * result + (this.valueExpr == null ? 0 : this.valueExpr.hashCode());
      return result;
   }

   public boolean equals(Object obj) {
      if (this == obj) {
         return true;
      } else if (obj == null) {
         return false;
      } else if (this.getClass() != obj.getClass()) {
         return false;
      } else {
         SQLCaseExpr other = (SQLCaseExpr)obj;
         if (this.elseExpr == null) {
            if (other.elseExpr != null) {
               return false;
            }
         } else if (!this.elseExpr.equals(other.elseExpr)) {
            return false;
         }

         if (!this.items.equals(other.items)) {
            return false;
         } else {
            if (this.valueExpr == null) {
               if (other.valueExpr != null) {
                  return false;
               }
            } else if (!this.valueExpr.equals(other.valueExpr)) {
               return false;
            }

            return true;
         }
      }
   }

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

      for(Item item : this.items) {
         x.addItem(item.clone());
      }

      if (this.valueExpr != null) {
         x.setValueExpr(this.valueExpr.clone());
      }

      if (this.elseExpr != null) {
         x.setElseExpr(this.elseExpr.clone());
      }

      return x;
   }

   public SQLDataType computeDataType() {
      for(Item item : this.items) {
         SQLExpr expr = item.getValueExpr();
         if (expr != null) {
            SQLDataType dataType = expr.computeDataType();
            if (dataType != null) {
               return dataType;
            }
         }
      }

      if (this.elseExpr != null) {
         return this.elseExpr.computeDataType();
      } else {
         return null;
      }
   }

   public String toString() {
      return SQLUtils.toSQLString(this, (DbType)((DbType)null));
   }

   public static class Item extends SQLObjectImpl implements SQLReplaceable, Serializable {
      private static final long serialVersionUID = 1L;
      private SQLExpr conditionExpr;
      private SQLExpr valueExpr;

      public Item() {
      }

      public Item(SQLExpr conditionExpr, SQLExpr valueExpr) {
         this.setConditionExpr(conditionExpr);
         this.setValueExpr(valueExpr);
      }

      public SQLExpr getConditionExpr() {
         return this.conditionExpr;
      }

      public void setConditionExpr(SQLExpr conditionExpr) {
         if (conditionExpr != null) {
            conditionExpr.setParent(this);
         }

         this.conditionExpr = conditionExpr;
      }

      public SQLExpr getValueExpr() {
         return this.valueExpr;
      }

      public void setValueExpr(SQLExpr valueExpr) {
         if (valueExpr != null) {
            valueExpr.setParent(this);
         }

         this.valueExpr = valueExpr;
      }

      protected void accept0(SQLASTVisitor visitor) {
         if (visitor.visit(this)) {
            if (this.conditionExpr != null) {
               this.conditionExpr.accept(visitor);
            }

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

         visitor.endVisit(this);
      }

      public int hashCode() {
         int prime = 31;
         int result = 1;
         result = 31 * result + (this.conditionExpr == null ? 0 : this.conditionExpr.hashCode());
         result = 31 * result + (this.valueExpr == null ? 0 : this.valueExpr.hashCode());
         return result;
      }

      public boolean equals(Object obj) {
         if (this == obj) {
            return true;
         } else if (obj == null) {
            return false;
         } else if (this.getClass() != obj.getClass()) {
            return false;
         } else {
            Item other = (Item)obj;
            if (this.conditionExpr == null) {
               if (other.conditionExpr != null) {
                  return false;
               }
            } else if (!this.conditionExpr.equals(other.conditionExpr)) {
               return false;
            }

            if (this.valueExpr == null) {
               if (other.valueExpr != null) {
                  return false;
               }
            } else if (!this.valueExpr.equals(other.valueExpr)) {
               return false;
            }

            return true;
         }
      }

      public Item clone() {
         Item x = new Item();
         if (this.conditionExpr != null) {
            x.setConditionExpr(this.conditionExpr.clone());
         }

         if (this.valueExpr != null) {
            x.setValueExpr(this.valueExpr.clone());
         }

         return x;
      }

      public boolean replace(SQLExpr expr, SQLExpr target) {
         if (this.valueExpr == expr) {
            this.setValueExpr(target);
            return true;
         } else if (this.conditionExpr == expr) {
            this.setConditionExpr(target);
            return true;
         } else {
            return false;
         }
      }
   }
}
