package com.chenyang.druid.sql.dialect.mysql.visitor.transform;

import com.chenyang.druid.sql.ast.SQLExpr;
import com.chenyang.druid.sql.ast.SQLName;
import com.chenyang.druid.sql.ast.SQLOrderBy;
import com.chenyang.druid.sql.ast.statement.SQLSelect;
import com.chenyang.druid.sql.ast.statement.SQLSelectItem;
import com.chenyang.druid.sql.ast.statement.SQLSelectOrderByItem;
import com.chenyang.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.chenyang.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;
import com.chenyang.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;
import com.chenyang.druid.util.FnvHash;
import java.util.ArrayList;
import java.util.List;

public class OrderByResolve extends OracleASTVisitorAdapter {
   static final long DBMS_RANDOM_VALUE = FnvHash.hashCode64("DBMS_RANDOM.value");

   public boolean visit(SQLSelect x) {
      SQLSelectQueryBlock queryBlock = x.getQueryBlock();
      if (queryBlock == null) {
         return super.visit((SQLSelect)x);
      } else {
         if (x.getOrderBy() != null && queryBlock.isForUpdate() && queryBlock.getOrderBy() == null) {
            queryBlock.setOrderBy(x.getOrderBy());
            x.setOrderBy((SQLOrderBy)null);
         }

         SQLOrderBy orderBy = queryBlock.getOrderBy();
         if (orderBy == null) {
            return super.visit((SQLSelect)x);
         } else {
            if (!queryBlock.selectItemHasAllColumn(false)) {
               List<SQLSelectOrderByItem> notContainsOrderBy = new ArrayList();

               for(SQLSelectOrderByItem orderByItem : orderBy.getItems()) {
                  SQLExpr orderByExpr = orderByItem.getExpr();
                  if (orderByExpr instanceof SQLName && ((SQLName)orderByExpr).hashCode64() != DBMS_RANDOM_VALUE) {
                     long hashCode64 = ((SQLName)orderByExpr).nameHashCode64();
                     SQLSelectItem selectItem = queryBlock.findSelectItem(hashCode64);
                     if (selectItem == null) {
                        queryBlock.addSelectItem(orderByExpr.clone());
                     }
                  }
               }

               if (notContainsOrderBy.size() > 0) {
                  for(SQLSelectOrderByItem orderByItem : notContainsOrderBy) {
                     queryBlock.addSelectItem(orderByItem.getExpr());
                  }

                  OracleSelectQueryBlock queryBlock1 = new OracleSelectQueryBlock();
                  queryBlock1.setFrom(queryBlock, "x");
                  x.setQuery(queryBlock1);
               }
            }

            return super.visit((SQLSelect)x);
         }
      }
   }
}
