package com.alibaba.druid.sql.ast.expr;

import com.alibaba.druid.DbType;
import com.alibaba.druid.FastsqlException;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLDataType;
import com.alibaba.druid.sql.ast.SQLDataTypeImpl;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.parser.ParserException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

public class SQLExprUtils {
   public static boolean equals(SQLExpr a, SQLExpr b) {
      if (a == b) {
         return true;
      } else if (a != null && b != null) {
         Class<?> clazz_a = a.getClass();
         Class<?> clazz_b = b.getClass();
         if (clazz_a == SQLPropertyExpr.class && clazz_b == SQLIdentifierExpr.class) {
            return ((SQLPropertyExpr)a).equals((SQLIdentifierExpr)b);
         } else if (clazz_a != clazz_b) {
            return false;
         } else if (clazz_a == SQLIdentifierExpr.class) {
            SQLIdentifierExpr x_a = (SQLIdentifierExpr)a;
            SQLIdentifierExpr x_b = (SQLIdentifierExpr)b;
            return x_a.hashCode() == x_b.hashCode();
         } else if (clazz_a == SQLBinaryOpExpr.class) {
            SQLBinaryOpExpr x_a = (SQLBinaryOpExpr)a;
            SQLBinaryOpExpr x_b = (SQLBinaryOpExpr)b;
            return x_a.equals(x_b);
         } else {
            return a.equals(b);
         }
      } else {
         return false;
      }
   }

   public static boolean isLiteralExpr(SQLExpr expr) {
      if (expr instanceof SQLLiteralExpr) {
         return true;
      } else if (!(expr instanceof SQLBinaryOpExpr)) {
         return false;
      } else {
         SQLBinaryOpExpr binary = (SQLBinaryOpExpr)expr;
         return isLiteralExpr(binary.left) && isLiteralExpr(binary.right);
      }
   }

   public static SQLExpr fromJavaObject(Object o) {
      return fromJavaObject(o, (TimeZone)null);
   }

   public static SQLExpr fromJavaObject(Object o, TimeZone timeZone) {
      if (o == null) {
         return new SQLNullExpr();
      } else if (o instanceof String) {
         return new SQLCharExpr((String)o);
      } else if (o instanceof BigDecimal) {
         return new SQLDecimalExpr((BigDecimal)o);
      } else if (!(o instanceof Byte) && !(o instanceof Short) && !(o instanceof Integer) && !(o instanceof Long) && !(o instanceof BigInteger)) {
         if (o instanceof Number) {
            return new SQLNumberExpr((Number)o);
         } else if (o instanceof Date) {
            return new SQLTimestampExpr((Date)o, timeZone);
         } else {
            throw new ParserException("not support class : " + o.getClass());
         }
      } else {
         return new SQLIntegerExpr((Number)o);
      }
   }

   public static SQLInListExpr conditionIn(String column, List<Object> values, TimeZone timeZone) {
      SQLInListExpr in = new SQLInListExpr();
      in.setExpr(SQLUtils.toSQLExpr(column));

      for(Object value : values) {
         in.addTarget(fromJavaObject(value, timeZone));
      }

      return in;
   }

   public static String quote(String str, DbType dbType, char quote) {
      SQLExpr expr;
      if (quote == '`') {
         expr = new SQLIdentifierExpr(str);
      } else if (quote == '"') {
         if (dbType != DbType.oracle && dbType != DbType.presto) {
            expr = new SQLCharExpr(str);
         } else {
            expr = new SQLIdentifierExpr(str);
         }
      } else {
         if (quote != '\'') {
            throw new FastsqlException("quote not support");
         }

         expr = new SQLCharExpr(str);
      }

      return SQLUtils.toSQLString(expr, (DbType)dbType);
   }

   public static SQLDataType createDataTypeFromJdbc(DbType dbType, int jdbType, Integer precision, Integer scale) {
      SQLDataType dataType;
      dataType = null;
      label30:
      switch (jdbType) {
         case 4:
            if (dbType == null) {
               return new SQLDataTypeImpl("integer");
            }

            switch (dbType) {
               case mysql:
                  return new SQLDataTypeImpl("int");
               default:
                  break label30;
            }
         case 12:
            switch (dbType) {
               case mysql:
                  return new SQLDataTypeImpl("varchar");
            }
      }

      if (dataType != null) {
         if (dbType != null) {
            dataType.setDbType(dbType);
         }

         return dataType;
      } else {
         throw new FastsqlException("type " + jdbType + " not support");
      }
   }
}
