package com.alibaba.druid.sql.dialect.hive.parser;

import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLAssignItem;
import com.alibaba.druid.sql.dialect.hive.ast.stmt.HiveShowStatement;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.parser.Token;

public class HiveShowParser extends SQLStatementParser {
   HiveShowParser(String sql) {
      super((SQLExprParser)(new HiveExprParser(sql)));
      this.dbType = DbType.hive;
   }

   public HiveShowParser(SQLExprParser exprParser) {
      super(exprParser);
      this.dbType = DbType.hive;
   }

   public HiveShowParser(Lexer lexer) {
      super((SQLExprParser)(new HiveExprParser(lexer)));
      this.dbType = DbType.hive;
   }

   public SQLStatement parseShow() {
      this.accept(Token.SHOW);
      HiveShowStatement stmt = new HiveShowStatement();
      if (this.lexer.token() == Token.CREATE) {
         this.accept(Token.CREATE);
         stmt.showType = "create table";
         this.accept(Token.TABLE);
      }

      if (this.lexer.token() == Token.MATERIALIZED) {
         this.accept(Token.MATERIALIZED);
         stmt.showType = "materialized views";
         this.acceptIdentifier("views");
      }

      if (this.lexer.identifierEquals("COMPACTIONS")) {
         this.acceptIdentifier("COMPACTIONS");
         stmt.showType = "compactions";
         stmt.showTypeValue = this.exprParser.name();
      }

      if (this.lexer.identifierEquals("DATABASES")) {
         stmt.showType = "DATABASES";
         this.acceptIdentifier("DATABASES");
      }

      if (this.lexer.identifierEquals("TABLES")) {
         stmt.showType = "TABLES";
         this.acceptIdentifier("TABLES");
      }

      if (this.lexer.identifierEquals("VIEWS")) {
         stmt.showType = "VIEWS";
         this.acceptIdentifier("VIEWS");
      }

      if (this.lexer.identifierEquals("VIEWS")) {
         stmt.showType = "VIEWS";
         this.acceptIdentifier("VIEWS");
      }

      if (this.lexer.token() == Token.TABLE) {
         stmt.showType = "TABLE EXTENDED";
         this.accept(Token.TABLE);
         this.acceptIdentifier("EXTENDED");
      }

      if (this.lexer.identifierEquals("VIEWS")) {
         stmt.showType = "VIEWS";
         this.acceptIdentifier("VIEWS");
      }

      if (this.lexer.identifierEquals("TBLPROPERTIES")) {
         stmt.showType = "TBLPROPERTIES";
         this.acceptIdentifier("TBLPROPERTIES");
      }

      if (this.lexer.identifierEquals("FORMATTED")) {
         stmt.showType = "FORMATTED ";
         this.acceptIdentifier("FORMATTED");
         if (this.lexer.token() == Token.INDEX) {
            stmt.showType = stmt.showType + "index";
            this.accept(Token.INDEX);
         }

         if (this.lexer.identifierEquals("INDEXES")) {
            stmt.showType = stmt.showType + "indexes";
            this.acceptIdentifier("INDEXES");
         }
      }

      if (this.lexer.token() == Token.INDEX) {
         stmt.showType = "index";
         this.accept(Token.INDEX);
      }

      if (this.lexer.identifierEquals("INDEXES")) {
         stmt.showType = "indexes";
         this.acceptIdentifier("INDEXES");
      }

      if (this.lexer.identifierEquals("COLUMNS")) {
         stmt.showType = "COLUMNS";
         this.acceptIdentifier("COLUMNS");
      }

      if (this.lexer.identifierEquals("FUNCTIONS")) {
         stmt.showType = "FUNCTIONS";
         this.acceptIdentifier("FUNCTIONS");
      }

      if (this.lexer.identifierEquals("CONF")) {
         stmt.showType = "CONF";
         this.acceptIdentifier("CONF");
         stmt.showTypeValue = this.exprParser.name();
      }

      if (this.lexer.identifierEquals("Transactions")) {
         stmt.showType = "Transactions";
         this.acceptIdentifier("Transactions");
      }

      if (this.lexer.identifierEquals("PRINCIPALS")) {
         this.acceptIdentifier("PRINCIPALS");
         stmt.showType = "PRINCIPALS";
         stmt.showTypeValue = this.exprParser.name();
      }

      if (this.lexer.identifierEquals("CURRENT")) {
         this.acceptIdentifier("CURRENT");
         this.acceptIdentifier("ROLES");
         stmt.showType = "CURRENT ROLES";
      }

      if (this.lexer.identifierEquals("ROLES")) {
         this.acceptIdentifier("ROLES");
         stmt.showType = "ROLES";
      }

      if (this.lexer.token() == Token.ROLE) {
         this.accept(Token.ROLE);
         this.accept(Token.GRANT);
         if (this.lexer.token() == Token.ROLE) {
            this.accept(Token.ROLE);
            stmt.showType = "ROLE GRANT ROLE";
         }

         if (this.lexer.token() == Token.USER) {
            this.accept(Token.USER);
            stmt.showType = "ROLE GRANT USER";
         }

         stmt.showTypeValue = this.exprParser.name();
      }

      if (this.lexer.token() == Token.GRANT) {
         this.accept(Token.GRANT);
         if (this.lexer.token() == Token.ROLE) {
            this.accept(Token.ROLE);
            stmt.showType = "GRANT ROLE";
         }

         if (this.lexer.token() == Token.USER) {
            this.accept(Token.USER);
            stmt.showType = "GRANT USER";
         }

         stmt.showTypeValue = this.exprParser.name();
         this.accept(Token.ON);
         if (this.lexer.token() == Token.ALL) {
            this.accept(Token.ALL);
            stmt.isAllTable = true;
         }

         if (this.lexer.token() == Token.TABLE) {
            this.accept(Token.TABLE);
            stmt.tableName = this.exprParser.name();
         }
      }

      if (this.lexer.token() == Token.ON) {
         this.accept(Token.ON);
         if (this.lexer.token() == Token.TABLE) {
            this.accept(Token.TABLE);
         }

         stmt.on = this.exprParser.name();
      }

      if (this.lexer.token() == Token.IN) {
         this.accept(Token.IN);
         stmt.in = this.exprParser.name();
      }

      if (this.lexer.token() == Token.FROM) {
         this.accept(Token.FROM);
         stmt.from = this.exprParser.name();
      }

      if (this.lexer.token() == Token.IN) {
         this.accept(Token.IN);
         stmt.in2 = this.exprParser.name();
      }

      if (this.lexer.token() == Token.FROM) {
         this.accept(Token.FROM);
         stmt.from2 = this.exprParser.name();
      }

      if (this.lexer.token() == Token.LIKE) {
         this.accept(Token.LIKE);
         stmt.like = this.exprParser.name();
      }

      if (this.lexer.token() == Token.PARTITION) {
         this.lexer.nextToken();
         this.accept(Token.LPAREN);

         while(true) {
            SQLAssignItem ptExpr = new SQLAssignItem();
            ptExpr.setTarget(this.exprParser.name());
            if (this.lexer.token() == Token.EQ || this.lexer.token() == Token.EQEQ) {
               this.lexer.nextTokenValue();
               SQLExpr ptValue = this.exprParser.expr();
               ptExpr.setValue(ptValue);
            }

            stmt.addPartition(ptExpr);
            if (this.lexer.token() != Token.COMMA) {
               this.accept(Token.RPAREN);
               break;
            }

            this.lexer.nextToken();
         }
      }

      if (this.lexer.token() == Token.SEMI) {
         this.accept(Token.SEMI);
      }

      return stmt;
   }

   public SQLStatement parseAbort() {
      this.accept(Token.ABORT);
      HiveShowStatement stmt = new HiveShowStatement();
      stmt.isAbort = true;
      this.lexer.nextToken();
      return stmt;
   }
}
