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

import com.chenyang.druid.FastsqlException;
import com.chenyang.druid.sql.ast.SQLExprImpl;
import com.chenyang.druid.sql.ast.SQLObject;
import com.chenyang.druid.sql.visitor.SQLASTVisitor;
import com.chenyang.druid.util.Utils;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;

public class SQLBinaryExpr extends SQLExprImpl implements SQLLiteralExpr, SQLValuableExpr {
   private String text;
   private transient Number val;

   public SQLBinaryExpr() {
   }

   public SQLBinaryExpr(String value) {
      this.text = value;
   }

   public String getText() {
      return this.text;
   }

   public Number getValue() {
      if (this.text == null) {
         return null;
      } else {
         if (this.val == null) {
            long[] words = new long[this.text.length() / 64 + 1];

            for(int i = this.text.length() - 1; i >= 0; --i) {
               char ch = this.text.charAt(i);
               if (ch == '1') {
                  int wordIndex = i >> 6;
                  words[wordIndex] |= 1L << this.text.length() - 1 - i;
               }
            }

            if (words.length == 1) {
               this.val = words[0];
            } else {
               byte[] bytes = new byte[words.length * 8];

               for(int i = 0; i < words.length; ++i) {
                  Utils.putLong(bytes, (words.length - 1 - i) * 8, words[i]);
               }

               this.val = new BigInteger(bytes);
            }
         }

         return this.val;
      }
   }

   public void setValue(String value) {
      this.text = value;
   }

   public void accept0(SQLASTVisitor visitor) {
      visitor.visit(this);
      visitor.endVisit(this);
   }

   public void output(Appendable buf) {
      try {
         buf.append("b'");
         buf.append(this.text);
         buf.append('\'');
      } catch (IOException ex) {
         throw new FastsqlException("output error", ex);
      }
   }

   public int hashCode() {
      int prime = 31;
      int result = 1;
      result = 31 * result + (this.text == null ? 0 : this.text.hashCode());
      return result;
   }

   public SQLBinaryExpr clone() {
      return new SQLBinaryExpr(this.text);
   }

   public List<SQLObject> getChildren() {
      return Collections.emptyList();
   }

   public boolean equals(Object obj) {
      if (this == obj) {
         return true;
      } else if (obj == null) {
         return false;
      } else if (this.getClass() != obj.getClass()) {
         return false;
      } else {
         SQLBinaryExpr other = (SQLBinaryExpr)obj;
         if (this.text == null) {
            if (other.text != null) {
               return false;
            }
         } else if (!this.text.equals(other.text)) {
            return false;
         }

         return true;
      }
   }
}
