package com.tibbo.aggregate.common.context;

import java.util.Objects;

import com.google.common.base.Strings;
import com.tibbo.aggregate.common.Log;
import com.tibbo.aggregate.common.data.Event;
import com.tibbo.aggregate.common.event.EventUtils;
import com.tibbo.aggregate.common.expression.Evaluator;
import com.tibbo.aggregate.common.expression.Expression;

public class FilteringEntityReference extends EntityReference
{
  protected String filterExpression;

  public FilteringEntityReference(String context, String entity, String filterExpression)
  {
    super(context, entity);
    this.filterExpression = filterExpression;
  }
  
  public void setFilterExpression(String filterExpression)
  {
    this.filterExpression = filterExpression;
  }
  
  public String getFilterExpression()
  {
    return filterExpression;
  }
  
  @Override
  public boolean equals(Object o)
  {
    if (this == o)
    {
      return true;
    }
    if (o == null || getClass() != o.getClass())
    {
      return false;
    }
    if (!super.equals(o))
    {
      return false;
    }
    
    FilteringEntityReference that = (FilteringEntityReference) o;
    
    return Objects.equals(filterExpression, that.filterExpression);
  }
  
  @Override
  public int hashCode()
  {
    return Objects.hash(super.hashCode(), filterExpression);
  }
  
  public boolean pass(Event ev, ContextManager<Context<?>> contextManager, CallerController caller)
  {
    try
    {
      if (Strings.isNullOrEmpty(filterExpression))
      {
        return true;
      }

      if (EventUtils.matchesToMask(entity, ev.getName()) && ContextUtils.matchesToMask(context, ev.getContext()))
      {
        Evaluator evaluator = new Evaluator(contextManager, caller);
        Context<?> dc = contextManager.get(ev.getContext(), caller);
        evaluator.setDefaultContext(dc);
        evaluator.setDefaultTable(ev.getData());
        return evaluator.evaluateToBoolean(new Expression(filterExpression));
      }
    }
    catch (Exception e)
    {
      Log.EVENTLOG.warn("Unable to filter an event: " + ev.toString(), e);
    }
    return false;
  }
}
