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

import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.statement.SQLCreateStatement;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLTableElement;
import com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObjectImpl;
import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGOptionValue;
import com.alibaba.druid.sql.dialect.postgresql.ast.expr.constraint.PGStorageParameter;
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 PGCreateTableStatement extends SQLCreateTableStatement implements PGSQLStatement, SQLCreateStatement {
   private TableType tableType;
   private SQLName ofType;
   private List<SQLExpr> parentTables = new ArrayList();
   private List<PGStorageParameter> parameters = new ArrayList();
   private OnCommit onCommit;
   private PGTableDistributedBy distributedBy;
   private Boolean withData;
   private Boolean withNoData;

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

   public TableType getTableType() {
      return this.tableType;
   }

   public void setTableType(TableType tableType) {
      this.tableType = tableType;
   }

   public List<SQLExpr> getParentTables() {
      return this.parentTables;
   }

   public void addParentTable(SQLExpr parentTable) {
      parentTable.setParent(this);
      this.parentTables.add(parentTable);
   }

   public void setParentTables(List<SQLExpr> parentTables) {
      this.parentTables = parentTables;
   }

   public void addStorageParameter(PGStorageParameter parameter) {
      parameter.setParent(this);
      this.parameters.add(parameter);
   }

   public List<PGStorageParameter> getParameters() {
      return this.parameters;
   }

   public void setParameters(List<PGStorageParameter> parameters) {
      this.parameters = parameters;
   }

   public OnCommit getOnCommit() {
      return this.onCommit;
   }

   public void setOnCommit(OnCommit onCommit) {
      this.onCommit = onCommit;
   }

   public PGTableDistributedBy getDistributedBy() {
      return this.distributedBy;
   }

   public void setDistributedBy(PGTableDistributedBy distributedBy) {
      this.distributedBy = distributedBy;
      distributedBy.setParent(this);
   }

   public SQLName getOfType() {
      return this.ofType;
   }

   public void setOfType(SQLName ofType) {
      this.ofType = ofType;
      ofType.setParent(this);
   }

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

   public void accept0(PGASTVisitor v) {
      if (v.visit(this)) {
         this.acceptChild(v, this.tableSource);
         this.acceptChild(v, this.ofType);
         this.acceptChild(v, this.tableElementList);
         this.acceptChild(v, this.parentTables);
         this.acceptChild(v, this.parameters);
         this.acceptChild(v, this.tablespace);
         this.acceptChild(v, this.distributedBy);
         this.acceptChild(v, this.partitionColumns);
      }

      v.endVisit(this);
   }

   public PGCreateTableStatement clone() {
      PGCreateTableStatement c = new PGCreateTableStatement();
      c.setTableType(this.tableType);
      c.setIfNotExiists(this.ifNotExists);
      c.setTableSource(this.tableSource.clone());
      if (this.ofType != null) {
         c.setOfType(this.ofType);
      }

      for(SQLTableElement sqlTableElement : c.tableElementList) {
         SQLTableElement col = sqlTableElement.clone();
         col.setParent(c);
         c.tableElementList.add(col);
      }

      for(SQLExpr parentTable : this.parentTables) {
         c.addParentTable(parentTable.clone());
      }

      for(PGStorageParameter parameter : this.parameters) {
         this.addStorageParameter(parameter.clone());
      }

      if (this.tablespace != null) {
         c.setTablespace(this.tablespace.clone());
      }

      if (this.distributedBy != null) {
         c.setDistributedBy(this.distributedBy.clone());
      }

      c.onCommit = this.onCommit;
      return c;
   }

   public static enum TableType {
      TEMPORARY,
      TEMP,
      GLOBAL_TEMPORARY,
      GLOBAL_TEMP,
      LOCAL_TEMPORARY,
      LOCAL_TEMP,
      GLOBAL_UNLOGGED,
      LOCAL_UNLOGGED,
      UNLOGGED;
   }

   public static enum OnCommit {
      preserveRows,
      deleteRows,
      drop;
   }

   public static class PGTableDistributedBy extends PGSQLObjectImpl {
      private List<PGOptionValue> columns = new ArrayList();
      private Option option;

      public void addColum(PGOptionValue column) {
         this.columns.add(column);
         column.setParent(this);
      }

      public List<PGOptionValue> getColumns() {
         return this.columns;
      }

      public void setColumns(List<PGOptionValue> columns) {
         this.columns = columns;
      }

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

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

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

      public void accept0(PGASTVisitor visitor) {
         if (visitor.visit(this)) {
            this.acceptChild(visitor, this.columns);
         }

         visitor.endVisit(this);
      }

      public PGTableDistributedBy clone() {
         PGTableDistributedBy c = new PGTableDistributedBy();

         for(PGOptionValue column : this.columns) {
            c.addColum(column.clone());
         }

         c.option = this.option;
         return c;
      }

      public static enum Option {
         by,
         randomly,
         replicated;
      }
   }
}
