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

import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.parser.Token;

public class OracleUpdateParser extends SQLStatementParser {
   public OracleUpdateParser(String sql) {
      super((SQLExprParser)(new OracleExprParser(sql)));
   }

   public OracleUpdateParser(Lexer lexer) {
      super((SQLExprParser)(new OracleExprParser(lexer)));
   }

   public OracleUpdateStatement parseUpdateStatement() {
      OracleUpdateStatement update = new OracleUpdateStatement();
      if (this.lexer.token() == Token.UPDATE) {
         this.lexer.nextToken();
         this.parseHints(update);
         if (this.lexer.identifierEquals("ONLY")) {
            update.setOnly(true);
         }

         SQLTableSource tableSource = this.exprParser.createSelectParser().parseTableSource();
         update.setTableSource(tableSource);
         if (update.getAlias() == null || update.getAlias().length() == 0) {
            update.setAlias(this.tableAlias());
         }
      }

      this.parseUpdateSet(update);
      this.parseWhere(update);
      this.parseReturn(update);
      this.parseErrorLoging(update);
      return update;
   }

   private void parseErrorLoging(OracleUpdateStatement update) {
      if (this.lexer.identifierEquals("LOG")) {
         throw new ParserException("TODO. " + this.lexer.info());
      }
   }

   private void parseReturn(OracleUpdateStatement update) {
      if (this.lexer.token() == Token.RETURN || this.lexer.token() == Token.RETURNING) {
         this.lexer.nextToken();

         while(true) {
            SQLExpr item = this.exprParser.expr();
            update.getReturning().add(item);
            if (this.lexer.token() != Token.COMMA) {
               this.accept(Token.INTO);

               while(true) {
                  item = this.exprParser.expr();
                  update.addReturningInto(item);
                  if (this.lexer.token() != Token.COMMA) {
                     return;
                  }

                  this.lexer.nextToken();
               }
            }

            this.lexer.nextToken();
         }
      }
   }

   private void parseHints(OracleUpdateStatement update) {
      this.exprParser.parseHints(update.getHints());
   }

   private void parseWhere(OracleUpdateStatement update) {
      if (this.lexer.token() == Token.WHERE) {
         this.lexer.nextToken();
         update.setWhere(this.exprParser.expr());
      }

   }
}
