package com.chenyang.druid.sql.dialect.gauss.ast.stmt;

import com.chenyang.druid.DbType;
import com.chenyang.druid.sql.ast.SQLExpr;
import com.chenyang.druid.sql.ast.SQLName;
import com.chenyang.druid.sql.ast.statement.SQLCreateStatement;
import com.chenyang.druid.sql.ast.statement.SQLCreateTableStatement;
import com.chenyang.druid.sql.ast.statement.SQLTableElement;
import com.chenyang.druid.sql.dialect.gauss.ast.GaussSQLObjectImpl;
import com.chenyang.druid.sql.dialect.gauss.ast.expr.GaussOptionValue;
import com.chenyang.druid.sql.dialect.gauss.ast.expr.constraint.GaussStorageParameter;
import com.chenyang.druid.sql.dialect.gauss.visitor.GaussASTVisitor;
import com.chenyang.druid.sql.visitor.SQLASTVisitor;
import java.util.ArrayList;
import java.util.List;

public class GaussCreateTableStatement extends SQLCreateTableStatement implements GaussSQLStatement, SQLCreateStatement {
   private TableType tableType;
   private SQLName ofType;
   private List<SQLExpr> parentTables = new ArrayList();
   private List<GaussStorageParameter> parameters = new ArrayList();
   private OnCommit onCommit;
   private GaussTableDistributedBy distributedBy;
   private Boolean withData;
   private Boolean withNoData;
   private Boolean as;
   private GaussSelectStatement query;

   public Boolean getWithData() {
      return this.withData;
   }

   public void setWithData(Boolean withData) {
      this.withData = withData;
   }

   public Boolean getWithNoData() {
      return this.withNoData;
   }

   public void setWithNoData(Boolean withNoData) {
      this.withNoData = withNoData;
   }

   public Boolean getAs() {
      return this.as;
   }

   public void setAs(Boolean as) {
      this.as = as;
   }

   public GaussSelectStatement getQuery() {
      return this.query;
   }

   public void setQuery(GaussSelectStatement query) {
      this.query = query;
   }

   public GaussCreateTableStatement() {
      this.dbType = DbType.gauss;
   }

   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(GaussStorageParameter parameter) {
      parameter.setParent(this);
      this.parameters.add(parameter);
   }

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

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

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

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

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

   public void setDistributedBy(GaussTableDistributedBy 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((GaussASTVisitor)visitor);
   }

   public void accept0(GaussASTVisitor 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 GaussCreateTableStatement clone() {
      GaussCreateTableStatement c = new GaussCreateTableStatement();
      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(GaussStorageParameter 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 GaussTableDistributedBy extends GaussSQLObjectImpl {
      private List<GaussOptionValue> columns = new ArrayList();
      private Option option;

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

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

      public void setColumns(List<GaussOptionValue> 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((GaussASTVisitor)visitor);
      }

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

         visitor.endVisit(this);
      }

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

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

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

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