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

import com.chenyang.druid.DbType;
import com.chenyang.druid.sql.SQLUtils;
import com.chenyang.druid.sql.ast.AutoIncrementType;
import com.chenyang.druid.sql.ast.SQLAnnIndex;
import com.chenyang.druid.sql.ast.SQLDataType;
import com.chenyang.druid.sql.ast.SQLDbTypedObject;
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.SQLObjectWithDataType;
import com.chenyang.druid.sql.ast.SQLPartitionBy;
import com.chenyang.druid.sql.ast.SQLReplaceable;
import com.chenyang.druid.sql.ast.expr.SQLCharExpr;
import com.chenyang.druid.sql.ast.expr.SQLIdentifierExpr;
import com.chenyang.druid.sql.ast.expr.SQLPropertyExpr;
import com.chenyang.druid.sql.visitor.SQLASTVisitor;
import java.util.ArrayList;
import java.util.List;

public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElement, SQLObjectWithDataType, SQLReplaceable, SQLDbTypedObject {
   protected DbType dbType;
   protected SQLName name;
   protected SQLDataType dataType;
   protected SQLExpr defaultExpr;
   protected final List<SQLColumnConstraint> constraints = new ArrayList(0);
   protected SQLExpr comment;
   protected Boolean enable;
   protected Boolean validate;
   protected Boolean rely;
   protected boolean autoIncrement = false;
   protected SQLExpr onUpdate;
   protected SQLExpr format;
   protected SQLExpr storage;
   protected SQLExpr charsetExpr;
   protected SQLExpr collateExpr;
   protected SQLExpr asExpr;
   protected boolean stored = false;
   protected boolean virtual = false;
   protected boolean visible = false;
   protected boolean invisible = false;
   protected AutoIncrementType sequenceType;
   protected boolean preSort = false;
   protected int preSortOrder = 0;
   protected Identity identity;
   protected SQLExpr generatedAlawsAs;
   protected SQLExpr delimiter;
   protected SQLExpr delimiterTokenizer;
   protected SQLExpr nlpTokenizer;
   protected SQLExpr valueType;
   protected boolean disableIndex = false;
   protected SQLExpr jsonIndexAttrsExpr;
   protected SQLAnnIndex annIndex;
   protected SQLExpr unitCount;
   protected SQLExpr unitIndex;
   protected SQLExpr step;
   protected SQLCharExpr encode;
   protected SQLCharExpr compression;
   protected List<SQLAssignItem> mappedBy;
   protected List<SQLAssignItem> colProperties;

   public Identity getIdentity() {
      return this.identity;
   }

   public void setIdentity(Identity identity) {
      if (identity != null) {
         identity.setParent(this);
      }

      this.identity = identity;
   }

   public Boolean getEnable() {
      return this.enable;
   }

   public void setEnable(Boolean enable) {
      this.enable = enable;
   }

   public Boolean getValidate() {
      return this.validate;
   }

   public void setValidate(Boolean validate) {
      this.validate = validate;
   }

   public Boolean getRely() {
      return this.rely;
   }

   public void setRely(Boolean rely) {
      this.rely = rely;
   }

   public SQLName getName() {
      return this.name;
   }

   public String getColumnName() {
      return this.name == null ? null : this.name.getSimpleName();
   }

   public long nameHashCode64() {
      return this.name == null ? 0L : this.name.hashCode64();
   }

   public String getNameAsString() {
      return this.name == null ? null : this.name.toString();
   }

   public void setName(SQLName name) {
      this.name = name;
   }

   public void setName(String name) {
      this.setName((SQLName)(new SQLIdentifierExpr(name)));
   }

   public SQLDataType getDataType() {
      return this.dataType;
   }

   public int jdbcType() {
      return this.dataType == null ? 1111 : this.dataType.jdbcType();
   }

   public void setDataType(SQLDataType dataType) {
      if (dataType != null) {
         dataType.setParent(this);
      }

      this.dataType = dataType;
   }

   public SQLExpr getDefaultExpr() {
      return this.defaultExpr;
   }

   public void setDefaultExpr(SQLExpr defaultExpr) {
      if (defaultExpr != null) {
         defaultExpr.setParent(this);
      }

      this.defaultExpr = defaultExpr;
   }

   public List<SQLColumnConstraint> getConstraints() {
      return this.constraints;
   }

   public boolean isPrimaryKey() {
      for(SQLColumnConstraint constraint : this.constraints) {
         if (constraint instanceof SQLColumnPrimaryKey) {
            return true;
         }
      }

      if (this.parent instanceof SQLCreateTableStatement) {
         return ((SQLCreateTableStatement)this.parent).isPrimaryColumn(this.nameHashCode64());
      } else {
         return false;
      }
   }

   public boolean isOnlyPrimaryKey() {
      for(SQLColumnConstraint constraint : this.constraints) {
         if (constraint instanceof SQLColumnPrimaryKey) {
            return true;
         }
      }

      if (this.parent instanceof SQLCreateTableStatement) {
         return ((SQLCreateTableStatement)this.parent).isPrimaryColumn(this.nameHashCode64());
      } else {
         return false;
      }
   }

   public boolean isPartitionBy() {
      if (!(this.parent instanceof SQLCreateTableStatement)) {
         return false;
      } else {
         SQLCreateTableStatement stmt = (SQLCreateTableStatement)this.parent;
         SQLPartitionBy partitioning = stmt.getPartitioning();
         if (partitioning == null) {
            return false;
         } else {
            return this.name == null ? false : partitioning.isPartitionByColumn(this.nameHashCode64());
         }
      }
   }

   public void addConstraint(SQLColumnConstraint constraint) {
      if (constraint != null) {
         constraint.setParent(this);
      }

      this.constraints.add(constraint);
   }

   protected void accept0(SQLASTVisitor visitor) {
      if (visitor.visit(this)) {
         this.acceptChild(visitor, this.name);
         this.acceptChild(visitor, this.dataType);
         this.acceptChild(visitor, this.defaultExpr);
         this.acceptChild(visitor, this.constraints);
      }

      visitor.endVisit(this);
   }

   public SQLExpr getComment() {
      return this.comment;
   }

   public void setComment(String comment) {
      SQLCharExpr expr;
      if (comment == null) {
         expr = null;
      } else {
         expr = new SQLCharExpr(comment);
      }

      this.setComment((SQLExpr)expr);
   }

   public void setComment(SQLExpr comment) {
      if (comment != null) {
         comment.setParent(this);
      }

      this.comment = comment;
   }

   public boolean isVirtual() {
      return this.virtual;
   }

   public void setVirtual(boolean virtual) {
      this.virtual = virtual;
   }

   public boolean isStored() {
      return this.stored;
   }

   public void setStored(boolean stored) {
      this.stored = stored;
   }

   public SQLExpr getCharsetExpr() {
      return this.charsetExpr;
   }

   public void setCharsetExpr(SQLExpr charsetExpr) {
      if (charsetExpr != null) {
         charsetExpr.setParent(this);
      }

      this.charsetExpr = charsetExpr;
   }

   public SQLExpr getCollateExpr() {
      return this.collateExpr;
   }

   public void setCollateExpr(SQLExpr x) {
      if (this.charsetExpr != null) {
         this.charsetExpr.setParent(this);
      }

      this.collateExpr = x;
   }

   public SQLExpr getAsExpr() {
      return this.asExpr;
   }

   public void setAsExpr(SQLExpr asExpr) {
      if (this.charsetExpr != null) {
         this.charsetExpr.setParent(this);
      }

      this.asExpr = asExpr;
   }

   public boolean isAutoIncrement() {
      return this.autoIncrement;
   }

   public void setAutoIncrement(boolean autoIncrement) {
      this.autoIncrement = autoIncrement;
   }

   public SQLExpr getOnUpdate() {
      return this.onUpdate;
   }

   public void setOnUpdate(SQLExpr onUpdate) {
      this.onUpdate = onUpdate;
   }

   public SQLExpr getFormat() {
      return this.format;
   }

   public void setFormat(SQLExpr format) {
      this.format = format;
   }

   public SQLExpr getStorage() {
      return this.storage;
   }

   public void setStorage(SQLExpr storage) {
      this.storage = storage;
   }

   public boolean replace(SQLExpr expr, SQLExpr target) {
      if (this.defaultExpr == expr) {
         this.setDefaultExpr(target);
         return true;
      } else if (this.name == expr) {
         this.setName((SQLName)target);
         return true;
      } else if (this.comment == expr) {
         this.setComment(target);
         return true;
      } else {
         return false;
      }
   }

   public void setUnitCount(SQLExpr unitCount) {
      if (unitCount != null) {
         unitCount.setParent(this);
      }

      this.unitCount = unitCount;
   }

   public String computeAlias() {
      String alias = null;
      if (this.name instanceof SQLIdentifierExpr) {
         alias = ((SQLIdentifierExpr)this.name).getName();
      } else if (this.name instanceof SQLPropertyExpr) {
         alias = ((SQLPropertyExpr)this.name).getName();
      }

      return SQLUtils.normalize(alias);
   }

   public SQLColumnDefinition clone() {
      SQLColumnDefinition x = new SQLColumnDefinition();
      x.setDbType(this.dbType);
      if (this.name != null) {
         x.setName(this.name.clone());
      }

      if (this.dataType != null) {
         x.setDataType(this.dataType.clone());
      }

      if (this.defaultExpr != null) {
         x.setDefaultExpr(this.defaultExpr.clone());
      }

      for(SQLColumnConstraint item : this.constraints) {
         SQLColumnConstraint itemCloned = item.clone();
         itemCloned.setParent(x);
         x.constraints.add(itemCloned);
      }

      if (this.comment != null) {
         x.setComment(this.comment.clone());
      }

      x.enable = this.enable;
      x.validate = this.validate;
      x.rely = this.rely;
      x.autoIncrement = this.autoIncrement;
      if (this.onUpdate != null) {
         x.setOnUpdate(this.onUpdate.clone());
      }

      if (this.format != null) {
         x.setFormat(this.format.clone());
      }

      if (this.storage != null) {
         x.setStorage(this.storage.clone());
      }

      if (this.charsetExpr != null) {
         x.setCharsetExpr(this.charsetExpr.clone());
      }

      if (this.collateExpr != null) {
         x.setCollateExpr(this.collateExpr.clone());
      }

      if (this.asExpr != null) {
         x.setAsExpr(this.asExpr.clone());
      }

      x.stored = this.stored;
      x.virtual = this.virtual;
      if (this.identity != null) {
         x.setIdentity(this.identity.clone());
      }

      if (this.delimiter != null) {
         x.setDelimiter(this.delimiter.clone());
      }

      if (this.valueType != null) {
         x.setValueType(this.valueType.clone());
      }

      if (this.nlpTokenizer != null) {
         x.setNplTokenizer(this.nlpTokenizer.clone());
      }

      x.preSort = this.preSort;
      x.preSortOrder = this.preSortOrder;
      if (this.jsonIndexAttrsExpr != null) {
         x.setJsonIndexAttrsExpr(this.jsonIndexAttrsExpr.clone());
      }

      if (this.annIndex != null) {
         x.setAnnIndex(this.annIndex.clone());
      }

      if (this.mappedBy != null) {
         for(SQLAssignItem item : this.mappedBy) {
            SQLAssignItem item2 = item.clone();
            item2.setParent(this);
            if (x.mappedBy == null) {
               x.mappedBy = new ArrayList();
            }

            x.mappedBy.add(item2);
         }
      }

      if (this.colProperties != null) {
         for(SQLAssignItem item : this.colProperties) {
            SQLAssignItem item2 = item.clone();
            item2.setParent(this);
            if (x.colProperties == null) {
               x.colProperties = new ArrayList();
            }

            x.colProperties.add(item2);
         }
      }

      return x;
   }

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

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

   public void simplify() {
      this.enable = null;
      this.validate = null;
      this.rely = null;
      if (this.name instanceof SQLIdentifierExpr) {
         SQLIdentifierExpr identExpr = (SQLIdentifierExpr)this.name;
         String columnName = identExpr.getName();
         String normalized = SQLUtils.normalize(columnName, this.dbType);
         if (normalized != columnName) {
            this.setName(normalized);
         }
      }

   }

   public boolean containsNotNullConstaint() {
      for(SQLColumnConstraint constraint : this.constraints) {
         if (constraint instanceof SQLNotNullConstraint) {
            return true;
         }
      }

      return false;
   }

   public SQLExpr getGeneratedAlawsAs() {
      return this.generatedAlawsAs;
   }

   public void setGeneratedAlawsAs(SQLExpr x) {
      if (x != null) {
         x.setParent(this);
      }

      this.generatedAlawsAs = x;
   }

   public boolean isVisible() {
      return this.visible;
   }

   public void setVisible(boolean visible) {
      this.visible = visible;
   }

   public SQLExpr getDelimiter() {
      return this.delimiter;
   }

   public boolean isDisableIndex() {
      return this.disableIndex;
   }

   public void setDisableIndex(boolean disableIndex) {
      this.disableIndex = disableIndex;
   }

   public void setDelimiter(SQLExpr x) {
      if (x != null) {
         x.setParent(this);
      }

      this.delimiter = x;
   }

   public SQLExpr getDelimiterTokenizer() {
      return this.delimiterTokenizer;
   }

   public void setDelimiterTokenizer(SQLExpr delimiterTokenizer) {
      this.delimiterTokenizer = delimiterTokenizer;
   }

   public SQLExpr getNlpTokenizer() {
      return this.nlpTokenizer;
   }

   public void setNlpTokenizer(SQLExpr nlpTokenizer) {
      this.nlpTokenizer = nlpTokenizer;
   }

   public SQLExpr getValueType() {
      return this.valueType;
   }

   public void setValueType(SQLExpr x) {
      if (x != null) {
         x.setParent(this);
      }

      this.valueType = x;
   }

   public boolean isPreSort() {
      return this.preSort;
   }

   public void setPreSort(boolean preSort) {
      this.preSort = preSort;
   }

   public int getPreSortOrder() {
      return this.preSortOrder;
   }

   public void setPreSortOrder(int preSortOrder) {
      this.preSortOrder = preSortOrder;
   }

   public SQLExpr getJsonIndexAttrsExpr() {
      return this.jsonIndexAttrsExpr;
   }

   public void setJsonIndexAttrsExpr(SQLExpr jsonIndexAttrsExpr) {
      this.jsonIndexAttrsExpr = jsonIndexAttrsExpr;
   }

   public SQLAnnIndex getAnnIndex() {
      return this.annIndex;
   }

   public void setAnnIndex(SQLAnnIndex x) {
      if (x != null) {
         x.setParent(this);
      }

      this.annIndex = x;
   }

   public AutoIncrementType getSequenceType() {
      return this.sequenceType;
   }

   public void setSequenceType(AutoIncrementType sequenceType) {
      this.sequenceType = sequenceType;
   }

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

   public SQLExpr getUnitCount() {
      return this.unitCount;
   }

   public SQLExpr getUnitIndex() {
      return this.unitIndex;
   }

   public void setUnitIndex(SQLExpr unitIndex) {
      if (unitIndex != null) {
         unitIndex.setParent(this);
      }

      this.unitIndex = unitIndex;
   }

   public SQLExpr getNplTokenizer() {
      return this.nlpTokenizer;
   }

   public void setNplTokenizer(SQLExpr x) {
      if (x != null) {
         x.setParent(this);
      }

      this.nlpTokenizer = x;
   }

   public SQLExpr getStep() {
      return this.step;
   }

   public void setStep(SQLExpr step) {
      if (step != null) {
         step.setParent(this);
      }

      this.step = step;
   }

   public List<SQLAssignItem> getMappedBy() {
      if (this.mappedBy == null) {
         this.mappedBy = new ArrayList();
      }

      return this.mappedBy;
   }

   public List<SQLAssignItem> getMappedByDirect() {
      return this.mappedBy;
   }

   public List<SQLAssignItem> getColProperties() {
      if (this.colProperties == null) {
         this.colProperties = new ArrayList();
      }

      return this.colProperties;
   }

   public SQLCharExpr getEncode() {
      return this.encode;
   }

   public void setEncode(SQLCharExpr encode) {
      this.encode = encode;
   }

   public SQLCharExpr getCompression() {
      return this.compression;
   }

   public void setCompression(SQLCharExpr compression) {
      this.compression = compression;
   }

   public List<SQLAssignItem> getColPropertiesDirect() {
      return this.colProperties;
   }

   public boolean isInvisible() {
      return this.invisible;
   }

   public void setInvisible(boolean invisible) {
      this.invisible = invisible;
   }

   public static class Identity extends SQLObjectImpl {
      private Integer seed;
      private Integer increment;
      private boolean notForReplication;
      private boolean cycle;
      private Integer minValue;
      private Integer maxValue;

      public Integer getSeed() {
         return this.seed;
      }

      public void setSeed(Integer seed) {
         this.seed = seed;
      }

      public Integer getIncrement() {
         return this.increment;
      }

      public void setIncrement(Integer increment) {
         this.increment = increment;
      }

      public boolean isCycle() {
         return this.cycle;
      }

      public void setCycle(boolean cycle) {
         this.cycle = cycle;
      }

      public Integer getMinValue() {
         return this.minValue;
      }

      public void setMinValue(Integer minValue) {
         this.minValue = minValue;
      }

      public Integer getMaxValue() {
         return this.maxValue;
      }

      public void setMaxValue(Integer maxValue) {
         this.maxValue = maxValue;
      }

      public boolean isNotForReplication() {
         return this.notForReplication;
      }

      public void setNotForReplication(boolean notForReplication) {
         this.notForReplication = notForReplication;
      }

      public void accept0(SQLASTVisitor visitor) {
         visitor.visit(this);
         visitor.endVisit(this);
      }

      public Identity clone() {
         Identity x = new Identity();
         x.seed = this.seed;
         x.increment = this.increment;
         x.cycle = this.cycle;
         x.minValue = this.minValue;
         x.maxValue = this.maxValue;
         x.notForReplication = this.notForReplication;
         return x;
      }
   }
}
