package net.sf.jasperreports.engine.fill;

import java.text.FieldPosition;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExpression;
import net.sf.jasperreports.engine.JRRuntimeException;

public abstract class JREvaluator {
  private JRFillParameter resourceBundle = null;
  
  private byte whenResourceMissingType;
  
  private JRFillParameter locale;
  
  public void init(Map parametersMap, Map fieldsMap, Map variablesMap, byte resourceMissingType) throws JRException {
    this.whenResourceMissingType = resourceMissingType;
    this.resourceBundle = (JRFillParameter)parametersMap.get("REPORT_RESOURCE_BUNDLE");
    this.locale = (JRFillParameter)parametersMap.get("REPORT_LOCALE");
    customizedInit(parametersMap, fieldsMap, variablesMap);
  }
  
  public String msg(String pattern, Object arg0) {
    return getMessageFormat(pattern).format(new Object[] { arg0 }, new StringBuffer(), (FieldPosition)null).toString();
  }
  
  public String msg(String pattern, Object arg0, Object arg1) {
    return getMessageFormat(pattern).format(new Object[] { arg0, arg1 }, new StringBuffer(), (FieldPosition)null).toString();
  }
  
  public String msg(String pattern, Object arg0, Object arg1, Object arg2) {
    return getMessageFormat(pattern).format(new Object[] { arg0, arg1, arg2 }, new StringBuffer(), (FieldPosition)null).toString();
  }
  
  public String msg(String pattern, Object[] args) {
    return getMessageFormat(pattern).format(args, new StringBuffer(), (FieldPosition)null).toString();
  }
  
  public String str(String key) {
    String str = null;
    try {
      str = ((ResourceBundle)this.resourceBundle.getValue()).getString(key);
    } catch (NullPointerException e) {
      str = handleMissingResource(key, e);
    } catch (MissingResourceException e) {
      str = handleMissingResource(key, e);
    } 
    return str;
  }
  
  public Object evaluate(JRExpression expression) throws JRExpressionEvalException {
    Object value = null;
    if (expression != null)
      try {
        value = evaluate(expression.getId());
      } catch (NullPointerException e) {
      
      } catch (OutOfMemoryError e) {
        throw e;
      } catch (Throwable e) {
        throw new JRExpressionEvalException(expression, e);
      }  
    return value;
  }
  
  public Object evaluateOld(JRExpression expression) throws JRExpressionEvalException {
    Object value = null;
    if (expression != null)
      try {
        value = evaluateOld(expression.getId());
      } catch (NullPointerException e) {
      
      } catch (OutOfMemoryError e) {
        throw e;
      } catch (Throwable e) {
        throw new JRExpressionEvalException(expression, e);
      }  
    return value;
  }
  
  public Object evaluateEstimated(JRExpression expression) throws JRExpressionEvalException {
    Object value = null;
    if (expression != null)
      try {
        value = evaluateEstimated(expression.getId());
      } catch (NullPointerException e) {
      
      } catch (OutOfMemoryError e) {
        throw e;
      } catch (Throwable e) {
        throw new JRExpressionEvalException(expression, e);
      }  
    return value;
  }
  
  protected String handleMissingResource(String key, Exception e) throws JRRuntimeException {
    switch (this.whenResourceMissingType) {
      case 2:
        str = "";
        return str;
      case 3:
        str = key;
        return str;
      case 4:
        throw new JRRuntimeException("Resource not found for key \"" + key + "\".", e);
    } 
    String str = null;
    return str;
  }
  
  protected abstract void customizedInit(Map paramMap1, Map paramMap2, Map paramMap3) throws JRException;
  
  protected abstract Object evaluate(int paramInt) throws Throwable;
  
  protected abstract Object evaluateOld(int paramInt) throws Throwable;
  
  protected abstract Object evaluateEstimated(int paramInt) throws Throwable;
  
  private MessageFormat getMessageFormat(String pattern) {
    MessageFormat messageFormat = new MessageFormat("");
    messageFormat.setLocale((Locale)this.locale.getValue());
    messageFormat.applyPattern(pattern);
    return messageFormat;
  }
}
