package util.sqlparse.visitor.oracle.visitor;

import bean.Column;
import bean.DataBase;
import bean.Synonym;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import util.sqlparse.visitor.common.ScopeDialector;
import util.sqlparse.visitor.common.memo.FieldMemo;
import util.sqlparse.visitor.common.memo.TableMemo;
import util.sqlparse.visitor.common.names.NameWrapper;
import util.sqlparse.visitor.common.scope.Scope;
import util.sqlparse.visitor.common.utils.SeqMap;
import util.sqlparse.visitor.oracle.OracleNameWrapper;

public class OracleScopeDialector extends ScopeDialector {
   List<FieldMemo> conflits = new ArrayList();

   public OracleScopeDialector() {
   }

   public OracleScopeDialector(Scope scope) {
      super(scope);
   }

   public String wrap(String text) {
      if (text == null) {
         return text;
      } else {
         if (text.startsWith("\"")) {
            text = text.substring(1, text.length() - 1);
            if (text.toUpperCase().equals(text)) {
               return text;
            }
         }

         return text.startsWith("\"") ? text : text.toUpperCase();
      }
   }

   public boolean expandAllColumns(TableMemo table, boolean isSub, List<FieldMemo> fields) {
      if (table != null && table.ref != null) {
         if (table.ref instanceof OracleSelectTableReference) {
            OracleSelectTableReference ref = (OracleSelectTableReference)table.ref;
            if (!(ref.getParent() instanceof OracleSelectQueryBlock)) {
               return true;
            } else {
               OracleSelectQueryBlock block = (OracleSelectQueryBlock)ref.getParent();
               if (ref.getExpr() instanceof SQLName) {
                  return true;
               } else {
                  SQLSelectItem item = (SQLSelectItem)block.getSelectList().get(0);
                  FieldMemo typeField = this.scope.getFieldByExpr(item.getExpr());
                  SQLExpr expr = item.getExpr();
                  if (!(expr instanceof SQLName)) {
                     return true;
                  } else {
                     String name = ((SQLName)expr).getSimpleName();
                     List<Column> columns = this.scope.context.getColumns(table.schema, table.name);
                     if (columns != null && columns.size() > 0) {
                        Iterator<Column> iterator = columns.iterator();

                        while(iterator.hasNext()) {
                           Column next = (Column)iterator.next();
                           if (!next.getDataType().equalsIgnoreCase(name)) {
                              iterator.remove();
                           }
                        }

                        for(Column column : columns) {
                           FieldMemo field = new FieldMemo();
                           field.table = table;
                           field.alias = column.getColumnName();
                           field.name = column.getColumnName();
                           field.isSelectItem = true;
                           field.typeField = typeField;
                           fields.add(field);
                        }
                     }

                     return false;
                  }
               }
            }
         } else {
            return true;
         }
      } else {
         return true;
      }
   }

   public String wrapAlias(String text) {
      if (text == null) {
         return null;
      } else if (text.contains("\"")) {
         return text;
      } else {
         return this.scope.context.getDataBase() != null && this.scope.context.getDataBase().isCaseSensitive() ? text : "\"" + text + "\"";
      }
   }

   public ScopeDialector clone(Scope scope) {
      return new OracleScopeDialector(scope);
   }

   public String wrapColumn(String schema, String table, String column) {
      OracleNameWrapper wrapper = new OracleNameWrapper(this.scope.context.getDataBase().simpleCache);
      NameWrapper.ColInfo colInfo = new NameWrapper.ColInfo();
      colInfo.schema = schema;
      colInfo.table = table;
      colInfo.column = column;
      wrapper.unwrapColumn(colInfo);
      return colInfo.column.toUpperCase().equals(colInfo.column) ? colInfo.column : "\"" + colInfo.column + "\"";
   }

   public boolean isEqual(String name1, String name2) {
      if (name1 == null && name2 != null) {
         return false;
      } else if (name1 != null && name2 == null) {
         return false;
      } else if (name1 == null && name2 == null) {
         return true;
      } else {
         String placeholder = "\"";
         if (!name1.startsWith(placeholder)) {
            name1 = placeholder + name1.toUpperCase() + placeholder;
         }

         if (!name2.startsWith(placeholder)) {
            name2 = placeholder + name2.toUpperCase() + placeholder;
         }

         return name1.equals(name2);
      }
   }

   public boolean addField(FieldMemo field) {
      SeqMap<String, FieldMemo> fieldMap = this.scope.getFieldMap();
      String qualifiedName = field.getQualifiedName();
      List<FieldMemo> children = field.children;
      Iterator<FieldMemo> iterator = children.iterator();

      while(iterator.hasNext()) {
         FieldMemo x = (FieldMemo)iterator.next();
         if (x.outside) {
            iterator.remove();
         }
      }

      if (children.size() > 0) {
         Iterator<FieldMemo> iterator1 = children.iterator();

         while(iterator1.hasNext()) {
            FieldMemo x = (FieldMemo)iterator1.next();
            if (!this.conflits.contains(x)) {
               iterator1.remove();
            }
         }

         for(FieldMemo exist : children) {
            if (!exist.outside) {
               exist.isSelectItem = field.isSelectItem;
            }
         }

         fieldMap.put(qualifiedName, field);
      } else {
         if (fieldMap.containsKey(qualifiedName)) {
            FieldMemo fieldMemo = (FieldMemo)fieldMap.get(qualifiedName);
            field.exprs.addAll(fieldMemo.exprs);
            if (fieldMemo.isSelectItem) {
               field.isSelectItem = true;
            }

            field.id = fieldMemo.id;
         }

         fieldMap.put(qualifiedName, field);
      }

      return true;
   }

   public void addConflits(List<FieldMemo> fields) {
      this.conflits.addAll(fields);
   }

   public Synonym getSynonym(String schema, String synonymName) {
      DataBase dataBase = this.scope.context.getDataBase();
      Map<String, Synonym> synonyms = dataBase.simpleCache.getSynonyms();
      if (synonymName.startsWith("\"")) {
         synonymName = synonymName.substring(1, synonymName.length() - 1);
      } else {
         synonymName = synonymName.toUpperCase();
      }

      Synonym s = (Synonym)synonyms.get(schema + "." + synonymName);
      return s != null && !"".equals(s) ? s : null;
   }
}
