package trail.interceptor;

import javax.ejb.*;
import java.util.*;
import java.io.Serializable;

//TODO: Fix the client
@Stateful
@Interceptors (Tracer.class)
public class InterceptorCalculator implements Calculator, Serializable {

  public ArrayList <Integer> starts = new ArrayList <Integer> ();
  public ArrayList <Integer> ends = new ArrayList <Integer> ();
  public ArrayList <Double> growthrates = new ArrayList <Double> ();
  public ArrayList <Double> savings = new ArrayList <Double> ();
  public ArrayList <Double> results = new ArrayList <Double> ();

  private String trace;

  /*
  @PostConstruct
  public void initialize () {
    // System.err.println("Init is called");
    starts = new ArrayList <Integer> ();
    ends = new ArrayList <Integer> ();
    growthrates = new ArrayList <Double> ();
    savings = new ArrayList <Double> ();
    results = new ArrayList <Double> ();
  }
  */

  public double calculate (int start, int end, double growthrate, double saving) {
    double tmp = Math.pow(1. + growthrate / 12., 12. * (end - start) + 1);
    double result = saving * 12. * (tmp - 1) / growthrate;

    starts.add(Integer.valueOf(start));
    ends.add(Integer.valueOf(end));
    growthrates.add(Double.valueOf(growthrate));
    savings.add(Double.valueOf(saving));
    results.add(Double.valueOf(result));

    return result;
  }

  public ArrayList <Integer> getStarts () {
    return starts;
  }

  public ArrayList <Integer> getEnds () {
    return ends;
  }

  public ArrayList <Double> getGrowthrates () {
    return growthrates;
  }

  public ArrayList <Double> getSavings () {
    return savings;
  }

  public ArrayList <Double> getResults () {
    return results;
  }

  @AroundInvoke
  public Object limitStateSize (InvocationContext ctx)
                                      throws Exception {

    // Remove the earliest entry when the history
    // list gets too long
    if (starts.size() > 4) {
      starts.remove (0);
      ends.remove (0);
      growthrates.remove (0);
      savings.remove (0);
      results.remove (0);
    }

    return ctx.proceed();
  }

  public void setTrace (String s) {
    trace = s;
  }

  public String getTrace () {
    return trace;
  }
}
