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

import com.chenyang.druid.DbType;
import com.chenyang.druid.sql.SQLUtils;
import com.chenyang.druid.sql.ast.SQLExpr;
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.ast.SQLStatement;
import com.chenyang.druid.sql.visitor.SQLASTVisitor;
import java.util.ArrayList;
import java.util.List;

public class SQLInsertStatement extends SQLInsertInto implements SQLStatement {
   protected SQLWithSubqueryClause with;
   protected boolean upsert = false;

   public void cloneTo(SQLInsertStatement x) {
      super.cloneTo(x);
      x.dbType = this.dbType;
      x.upsert = this.upsert;
      x.afterSemi = this.afterSemi;
      if (this.with != null) {
         x.setWith(this.with.clone());
      }

   }

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

   protected void accept0(SQLASTVisitor visitor) {
      if (visitor.visit(this)) {
         this.acceptChild(visitor, this.tableSource);
         this.acceptChild(visitor, this.columns);
         this.acceptChild(visitor, this.valuesList);
         this.acceptChild(visitor, this.query);
      }

      visitor.endVisit(this);
   }

   public List<SQLObject> getChildren() {
      List<SQLObject> children = new ArrayList();
      children.add(this.tableSource);
      children.addAll(this.columns);
      children.addAll(this.valuesList);
      if (this.query != null) {
         children.add(this.query);
      }

      return children;
   }

   public boolean isUpsert() {
      return this.upsert;
   }

   public void setUpsert(boolean upsert) {
      this.upsert = upsert;
   }

   public DbType getDbType() {
      return this.dbType;
   }

   public void setDbType(DbType dbType) {
      this.dbType = dbType;
   }

   public boolean isAfterSemi() {
      return this.afterSemi;
   }

   public void setAfterSemi(boolean afterSemi) {
      this.afterSemi = afterSemi;
   }

   public SQLWithSubqueryClause getWith() {
      return this.with;
   }

   public void setWith(SQLWithSubqueryClause with) {
      if (with != null) {
         with.setParent(this);
      }

      this.with = with;
   }

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

   public static class ValuesClause extends SQLObjectImpl implements SQLReplaceable {
      private final List values;
      private transient String originalString;
      private transient int replaceCount;

      public ValuesClause() {
         this(new ArrayList());
      }

      public ValuesClause clone() {
         ValuesClause x = new ValuesClause(new ArrayList(this.values.size()));

         for(Object v : this.values) {
            x.addValue(v);
         }

         return x;
      }

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

         return false;
      }

      public ValuesClause(List<SQLExpr> values) {
         this.values = values;

         for(int i = 0; i < values.size(); ++i) {
            ((SQLExpr)values.get(i)).setParent(this);
         }

      }

      public ValuesClause(List values, SQLObject parent) {
         this.values = values;

         for(int i = 0; i < values.size(); ++i) {
            Object val = values.get(i);
            if (val instanceof SQLObject) {
               ((SQLObject)val).setParent(this);
            }
         }

         this.parent = parent;
      }

      public void addValue(Object value) {
         if (value instanceof SQLObject) {
            ((SQLObject)value).setParent(this);
         }

         this.values.add(value);
      }

      public void addValue(SQLExpr value) {
         value.setParent(this);
         this.values.add(value);
      }

      public List<SQLExpr> getValues() {
         return this.values;
      }

      protected void accept0(SQLASTVisitor visitor) {
         if (visitor.visit(this)) {
            for(int i = 0; i < this.values.size(); ++i) {
               Object item = this.values.get(i);
               if (item instanceof SQLObject) {
                  SQLObject value = (SQLObject)item;
                  value.accept(visitor);
               }
            }
         }

         visitor.endVisit(this);
      }

      public String getOriginalString() {
         return this.originalString;
      }

      public void setOriginalString(String originalString) {
         this.originalString = originalString;
      }

      public int getReplaceCount() {
         return this.replaceCount;
      }

      public void incrementReplaceCount() {
         ++this.replaceCount;
      }
   }
}
