package com.alibaba.druid.sql.dialect.postgresql.ast.stmt.alterTable;

import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.statement.SQLAssignItem;
import com.alibaba.druid.sql.ast.statement.SQLColumnConstraint;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObject;
import com.alibaba.druid.sql.dialect.postgresql.ast.expr.constraint.PGConstraint;
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import java.util.ArrayList;
import java.util.List;

public class PGColumnDefinition extends SQLColumnDefinition implements PGSQLObject {
   private boolean isWith = false;
   private SQLExpr type;
   private List<SQLExpr> encodings = new ArrayList();
   private PGConstraint tableConstraint;
   private SQLExprTableSource like;
   private List<ColumnLikeOption> likeOptions = new ArrayList();
   private List<PGConstraint.PGReference> columnReferenceStorageDirectives = new ArrayList();

   public PGColumnDefinition() {
      this.dbType = DbType.postgresql;
   }

   public void addColumnReferenceStorageDirective(PGConstraint.PGReference reference) {
      reference.setParent(this);
      this.columnReferenceStorageDirectives.add(reference);
   }

   public List<PGConstraint.PGReference> getColumnReferenceStorageDirectives() {
      return this.columnReferenceStorageDirectives;
   }

   public void setColumnReferenceStorageDirectives(List<PGConstraint.PGReference> columnReferenceStorageDirectives) {
      this.columnReferenceStorageDirectives = columnReferenceStorageDirectives;
   }

   public SQLExpr getType() {
      return this.type;
   }

   public void setType(SQLExpr type) {
      this.type = type;
   }

   public PGConstraint getTableConstraint() {
      return this.tableConstraint;
   }

   public void setTableConstraint(PGConstraint tableConstraint) {
      this.tableConstraint = tableConstraint;
      tableConstraint.setParent(this);
   }

   public SQLExprTableSource getLike() {
      return this.like;
   }

   public void setLike(SQLExprTableSource like) {
      like.setParent(this);
      this.like = like;
   }

   public void addOption(ColumnLikeOption option) {
      this.likeOptions.add(option);
   }

   public List<ColumnLikeOption> getLikeOptions() {
      return this.likeOptions;
   }

   public void setLikeOptions(List<ColumnLikeOption> likeOptions) {
      this.likeOptions = likeOptions;
   }

   public void addLikeOptions(ColumnLikeOption likeOption) {
      this.likeOptions.add(likeOption);
   }

   public boolean isWith() {
      return this.isWith;
   }

   public void setWith(boolean with) {
      this.isWith = with;
   }

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

   public void accept0(PGASTVisitor visitor) {
      if (visitor.visit(this)) {
         this.acceptChild(visitor, this.name);
         this.acceptChild(visitor, this.type);
         this.acceptChild(visitor, this.collateExpr);
         this.acceptChild(visitor, this.defaultExpr);
         this.acceptChild(visitor, this.constraints);
         this.acceptChild(visitor, this.encodings);
         this.acceptChild(visitor, this.tableConstraint);
         this.acceptChild(visitor, this.like);
         this.acceptChild(visitor, this.columnReferenceStorageDirectives);
      }

      visitor.endVisit(this);
   }

   public void addEncoding(SQLExpr encoding) {
      encoding.setParent(this);
      this.encodings.add(encoding);
   }

   public List<SQLExpr> getEncodings() {
      return this.encodings;
   }

   public void setEncodings(List<SQLExpr> encodings) {
      this.encodings = encodings;
   }

   public PGColumnDefinition clone() {
      PGColumnDefinition x = new PGColumnDefinition();
      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);
         }
      }

      if (this.encodings != null && this.encodings.size() > 0) {
         for(SQLExpr encoding : this.encodings) {
            x.addEncoding(encoding.clone());
         }
      }

      return x;
   }

   public static class ColumnLikeOption {
      private IncludeType includeType;
      private OptionType option;

      public IncludeType getIncludeType() {
         return this.includeType;
      }

      public void setIncludeType(IncludeType includeType) {
         this.includeType = includeType;
      }

      public OptionType getOption() {
         return this.option;
      }

      public void setOption(OptionType option) {
         this.option = option;
      }

      public ColumnLikeOption clone() {
         ColumnLikeOption c = new ColumnLikeOption();
         c.includeType = this.includeType;
         c.option = this.option;
         return c;
      }

      public static enum IncludeType {
         including,
         excluding;
      }

      public static enum OptionType {
         defaults,
         constraints,
         indexes,
         storage,
         comments,
         all;
      }
   }
}
