package org.infinispan.query.objectfilter.impl.syntax;

import java.util.Map;

/**
 * @author anistor@redhat.com
 * @since 7.0
 */
public final class LikeExpr implements PrimaryPredicateExpr {

   public static final char SINGLE_CHARACTER_WILDCARD = '_';

   public static final char MULTIPLE_CHARACTERS_WILDCARD = '%';

   public static final char DEFAULT_ESCAPE_CHARACTER = '\\';

   private final ValueExpr child;
   private final Object pattern;

   public LikeExpr(ValueExpr child, Object pattern) {
      this.child = child;
      this.pattern = pattern;
   }

   @Override
   public ValueExpr getChild() {
      return child;
   }

   public String getPattern(Map<String, Object> namedParameters) {
      if (pattern instanceof ConstantValueExpr.ParamPlaceholder) {
         String paramName = ((ConstantValueExpr.ParamPlaceholder) pattern).getName();
         if (namedParameters == null) {
            throw new IllegalStateException("Missing value for parameter " + paramName);
         }
         String p = (String) namedParameters.get(paramName);
         if (p == null) {
            throw new IllegalStateException("Missing value for parameter " + paramName);
         }
         return p;
      } else {
         return (String) pattern;
      }
   }

   public char getEscapeChar() {
      return DEFAULT_ESCAPE_CHARACTER;
   }

   @Override
   public <T> T acceptVisitor(Visitor<?, ?> visitor) {
      return (T) visitor.visit(this);
   }

   @Override
   public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;
      LikeExpr likeExpr = (LikeExpr) o;
      return pattern.equals(likeExpr.pattern) && child.equals(likeExpr.child);
   }

   @Override
   public int hashCode() {
      return 31 * child.hashCode() + pattern.hashCode();
   }

   @Override
   public String toString() {
      return "LIKE(" + child + ", " + pattern + ')';
   }

   @Override
   public void appendQueryString(StringBuilder sb) {
      child.appendQueryString(sb);
      sb.append(" LIKE '");
      sb.append(pattern);
      sb.append("'");
   }
}
