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

import com.chenyang.druid.sql.SQLUtils;
import com.chenyang.druid.sql.ast.SQLExpr;
import com.chenyang.druid.sql.ast.SQLIndex;
import com.chenyang.druid.sql.ast.SQLIndexDefinition;
import com.chenyang.druid.sql.ast.SQLName;
import com.chenyang.druid.sql.ast.expr.SQLIntegerExpr;
import com.chenyang.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.chenyang.druid.sql.ast.statement.SQLAssignItem;
import com.chenyang.druid.sql.ast.statement.SQLColumnDefinition;
import com.chenyang.druid.sql.ast.statement.SQLConstraintImpl;
import com.chenyang.druid.sql.ast.statement.SQLSelectOrderByItem;
import com.chenyang.druid.sql.ast.statement.SQLTableElement;
import com.chenyang.druid.sql.dialect.mysql.ast.MySqlObject;
import com.chenyang.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
import com.chenyang.druid.sql.visitor.SQLASTVisitor;
import java.util.List;

public class MySqlTableIndex extends SQLConstraintImpl implements SQLTableElement, SQLIndex, MySqlObject {
   private SQLIndexDefinition indexDefinition = new SQLIndexDefinition();

   public MySqlTableIndex() {
      this.indexDefinition.setParent(this);
   }

   public SQLIndexDefinition getIndexDefinition() {
      return this.indexDefinition;
   }

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

   public String getIndexType() {
      return this.indexDefinition.getType();
   }

   public void setIndexType(String indexType) {
      this.indexDefinition.setType(indexType);
   }

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

   public List<SQLSelectOrderByItem> getColumns() {
      return this.indexDefinition.getColumns();
   }

   public void addColumn(SQLSelectOrderByItem column) {
      if (column != null) {
         column.setParent(this);
      }

      this.indexDefinition.getColumns().add(column);
   }

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

   public void accept0(MySqlASTVisitor visitor) {
      if (visitor.visit(this)) {
         if (this.indexDefinition.getName() != null) {
            this.indexDefinition.getName().accept(visitor);
         }

         for(int i = 0; i < this.indexDefinition.getColumns().size(); ++i) {
            SQLSelectOrderByItem item = (SQLSelectOrderByItem)this.indexDefinition.getColumns().get(i);
            if (item != null) {
               item.accept(visitor);
            }
         }

         for(int i = 0; i < this.indexDefinition.getCovering().size(); ++i) {
            SQLName item = (SQLName)this.indexDefinition.getCovering().get(i);
            if (item != null) {
               item.accept(visitor);
            }
         }
      }

      visitor.endVisit(this);
   }

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

   public boolean applyColumnRename(SQLName columnName, SQLColumnDefinition to) {
      for(SQLSelectOrderByItem orderByItem : this.getColumns()) {
         SQLExpr expr = orderByItem.getExpr();
         if (expr instanceof SQLName && SQLUtils.nameEquals((SQLName)expr, columnName)) {
            orderByItem.setExpr(to.getName().clone());
            return true;
         }

         if (expr instanceof SQLMethodInvokeExpr && SQLUtils.nameEquals(((SQLMethodInvokeExpr)expr).getMethodName(), columnName.getSimpleName()) && 1 == ((SQLMethodInvokeExpr)expr).getArguments().size() && ((SQLMethodInvokeExpr)expr).getArguments().get(0) instanceof SQLIntegerExpr) {
            if (to.getDataType().hasKeyLength() && 1 == to.getDataType().getArguments().size() && to.getDataType().getArguments().get(0) instanceof SQLIntegerExpr) {
               int newKeyLength = ((SQLIntegerExpr)to.getDataType().getArguments().get(0)).getNumber().intValue();
               int oldKeyLength = ((SQLIntegerExpr)((SQLMethodInvokeExpr)expr).getArguments().get(0)).getNumber().intValue();
               if (newKeyLength > oldKeyLength) {
                  ((SQLMethodInvokeExpr)expr).setMethodName(to.getName().getSimpleName());
                  return true;
               }
            }

            orderByItem.setExpr(to.getName().clone());
            return true;
         }
      }

      return false;
   }

   public boolean applyDropColumn(SQLName columnName) {
      for(int i = this.indexDefinition.getColumns().size() - 1; i >= 0; --i) {
         SQLExpr expr = ((SQLSelectOrderByItem)this.indexDefinition.getColumns().get(i)).getExpr();
         if (expr instanceof SQLName && SQLUtils.nameEquals((SQLName)expr, columnName)) {
            this.indexDefinition.getColumns().remove(i);
            return true;
         }

         if (expr instanceof SQLMethodInvokeExpr && SQLUtils.nameEquals(((SQLMethodInvokeExpr)expr).getMethodName(), columnName.getSimpleName())) {
            this.indexDefinition.getColumns().remove(i);
            return true;
         }
      }

      return false;
   }

   public void addOption(String name, SQLExpr value) {
      this.indexDefinition.addOption(name, value);
   }

   public SQLExpr getOption(String name) {
      return this.indexDefinition.getOption(name);
   }

   protected SQLExpr getOption(long hash64) {
      return this.indexDefinition.getOption(hash64);
   }

   public String getDistanceMeasure() {
      return this.indexDefinition.getDistanceMeasure();
   }

   public String getAlgorithm() {
      return this.indexDefinition.getAlgorithm();
   }

   public List<SQLAssignItem> getOptions() {
      return this.indexDefinition.getCompatibleOptions();
   }

   public SQLExpr getComment() {
      return this.indexDefinition.getOptions().getComment();
   }

   public void setComment(SQLExpr x) {
      this.indexDefinition.getOptions().setComment(x);
   }

   public SQLExpr getDbPartitionBy() {
      return this.indexDefinition.getDbPartitionBy();
   }

   public void setDbPartitionBy(SQLExpr x) {
      this.indexDefinition.setDbPartitionBy(x);
   }

   public SQLExpr getTablePartitions() {
      return this.indexDefinition.getTbPartitions();
   }

   public void setTablePartitions(SQLExpr x) {
      this.indexDefinition.setTbPartitions(x);
   }

   public SQLExpr getTablePartitionBy() {
      return this.indexDefinition.getTbPartitionBy();
   }

   public void setTablePartitionBy(SQLExpr x) {
      this.indexDefinition.setTbPartitionBy(x);
   }

   public void setCovering(List<SQLName> covering) {
      this.indexDefinition.setCovering(covering);
   }

   public boolean isGlobal() {
      return this.indexDefinition.isGlobal();
   }

   public void setGlobal(boolean global) {
      this.indexDefinition.setGlobal(global);
   }

   public boolean isLocal() {
      return this.indexDefinition.isLocal();
   }

   public void setLocal(boolean local) {
      this.indexDefinition.setLocal(local);
   }

   public List<SQLName> getCovering() {
      return this.indexDefinition.getCovering();
   }

   public SQLName getIndexAnalyzerName() {
      return this.indexDefinition.getIndexAnalyzerName();
   }

   public void setIndexAnalyzerName(SQLName indexAnalyzerName) {
      this.indexDefinition.setIndexAnalyzerName(indexAnalyzerName);
   }

   public SQLName getQueryAnalyzerName() {
      return this.indexDefinition.getQueryAnalyzerName();
   }

   public void setQueryAnalyzerName(SQLName queryAnalyzerName) {
      this.indexDefinition.setQueryAnalyzerName(queryAnalyzerName);
   }

   public SQLName getWithDicName() {
      return this.indexDefinition.getWithDicName();
   }

   public void setWithDicName(SQLName withDicName) {
      this.indexDefinition.setWithDicName(withDicName);
   }

   public SQLName getAnalyzerName() {
      return this.indexDefinition.getAnalyzerName();
   }

   public void setAnalyzerName(SQLName analyzerName) {
      this.indexDefinition.setAnalyzerName(analyzerName);
   }
}
