package util.sqlparse.visitor.postgresql.visitor;

import bean.Column;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import java.util.ArrayList;
import java.util.List;
import util.sqlparse.visitor.common.Context;
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.scope.VirtualScope;
import util.sqlparse.visitor.postgresql.PostgresqlNameWrapper;

public class PostgresqlScopeDialector extends ScopeDialector {
   private final String ALIAS_COLUMN_TAG = "alias-column";

   public PostgresqlScopeDialector() {
   }

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

   public String wrap(String text) {
      if (text == null) {
         return text;
      } else {
         return text.startsWith("\"") ? text : text.toLowerCase();
      }
   }

   public boolean expandAllColumns(TableMemo table, boolean isSub, List<FieldMemo> fields) {
      return table != null && table.ref != null ? true : 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 PostgresqlScopeDialector(scope);
   }

   public String wrapColumn(String schema, String table, String column) {
      PostgresqlNameWrapper wrapper = new PostgresqlNameWrapper(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 List<FieldMemo> getColumns(TableMemo table) {
      Context context = this.scope.context;
      List<Column> columns = context.getColumns(table.schema, table.name);
      if (table.ref == null) {
         return null;
      } else if (!(table.ref instanceof SQLExprTableSource)) {
         return null;
      } else {
         List<SQLName> cols = ((SQLExprTableSource)table.ref).getColumns();
         if (cols != null && cols.size() != 0) {
            Scope current = this.scope.getCurrent();
            VirtualScope vscope = new VirtualScope(table.ref);
            current.append(vscope);
            List<FieldMemo> fields = new ArrayList();

            for(int i = 0; i < columns.size(); ++i) {
               Column column = (Column)columns.get(i);
               FieldMemo raw = new FieldMemo();
               raw.name = column.getColumnName();
               raw.table = table;
               raw.tables.add(table);
               raw.alias = raw.name;
               raw.atom = true;
               raw.alias = raw.name;
               vscope.addField(raw);
               String aliasName = i < cols.size() ? ((SQLName)cols.get(i)).getSimpleName() : raw.name;
               FieldMemo alias = new FieldMemo();
               alias.putAttribute("alias-column");
               alias.name = aliasName;
               alias.alias = alias.name;
               alias.isSelectItem = true;
               alias.atom = false;
               alias.table = table;
               alias.tables.add(table);
               alias.children.add(raw);
               fields.add(alias);
               current.addField(alias);
            }

            return fields;
         } else {
            return null;
         }
      }
   }
}
