package blog;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import blog.bn.BasicVar;
import blog.bn.BayesNetVar;
import blog.common.FilteredIterator;
import blog.model.ArgSpecQuery;
import blog.model.Evidence;
import blog.model.Model;
import blog.model.Query;
import blog.model.SymbolEvidenceStatement;
import blog.model.ValueEvidenceStatement;
import blog.type.Timestep;
import blog.world.PartialWorld;

/**
 * A class defining static helper methods on basic interfaces (therefore not
 * belonging to any of their specific implementations), regarding temporal
 * aspects (DBLOG) (general ones are in {@link BLOGUtil}.
 * 
 * @author Rodrigo
 * @author cberzan
 */
public class DBLOGUtil {
  /**
   * Returns a string obtained by replacing all identifiers <code>t</code> in a
   * given string by the string representation of a timestep the index of which
   * is given.
   */
  public static String replaceTByTimeStep(String string, int timestepIndex) {
    return string.replaceAll("\\bt\\b", "@" + timestepIndex);
  }

  /**
   * Returns the query obtained by instantiating a query string with a given
   * time step.
   */
  public static ArgSpecQuery getQueryForTimestep(String queryString,
      Model model, int timestepIndex) {
    String queryForLastestTimestepString = DBLOGUtil.replaceTByTimeStep(
        queryString, timestepIndex);
    ArgSpecQuery query = BLOGUtil.parseQuery_NE("query "
        + queryForLastestTimestepString + ";", model);
    return query;
  }

  /**
   * An iterator over the time step indices present in a partial world.
   */
  public static class TimestepIndicesIterator extends FilteredIterator {
    public TimestepIndicesIterator(PartialWorld world) {
      super(world.getInstantiatedVars().iterator());
    }

    public Object filter(int index, Object varObj) {
      BayesNetVar var = (BayesNetVar) varObj;
      int timestepIndex = var.maxTimestep().getValue();
      if (timestepIndex < 0 || alreadyReturned.contains(timestepIndex)) {
        // Don't want to return the same timestep twice.
        return null;
      }
      alreadyReturned.add(timestepIndex);
      return timestepIndex;
    }

    private HashSet<Integer> alreadyReturned = new HashSet<Integer>();
  }

  /**
   * Returns an iterator over the time step indices present in a partial world.
   */
  public static Iterator getTimestepIndicesIterator(PartialWorld world) {
    return new TimestepIndicesIterator(world);
  }

  /**
   * remove the temporal variables from the possible world that are
   * different from the specified timestep
   * 
   * @param largest
   * @param world
   */
  public static void removeVarsAtDiffTimestep(Timestep largest,
      PartialWorld world) {
    LinkedList instantiatedVars = new LinkedList(world.getInstantiatedVars());
    Iterator varIt = instantiatedVars.iterator();
    while (varIt.hasNext()) {
      BasicVar var = (BasicVar) varIt.next();
      Timestep timestep = var.maxTimestep();
      if (timestep != null && timestep != largest) {
        world.setValue(var, null);
      }
    }
  }

  /**
   * Split evidence by the timestep they refer to.
   * Atemporal evidence is assigned to timestep null.
   */
  public static Map<Timestep, Evidence> splitEvidenceInTime(Evidence evidence) {
    // First we accumulate all statements for each timestep.
    Map<Timestep, List<Object>> table = new HashMap<Timestep, List<Object>>();
    for (ValueEvidenceStatement statement : evidence.getValueEvidence()) {
      Timestep maxTimestep = statement.getLeftSide().maxTimestep();
      List<Object> statements = table.get(maxTimestep);
      if (statements == null) {
        statements = new LinkedList<Object>();
        table.put(maxTimestep, statements);
      }
      statements.add(statement);
    }
    for (SymbolEvidenceStatement statement : evidence.getSymbolEvidence()) {
      Timestep maxTimestep = statement.getSetSpec().maxTimestep();
      List<Object> statements = table.get(maxTimestep);
      if (statements == null) {
        statements = new LinkedList<Object>();
        table.put(maxTimestep, statements);
      }
      statements.add(statement);
    }
    // Then we convert each list of statements to an Evidence object.
    Map<Timestep, Evidence> result = new HashMap<Timestep, Evidence>();
    for (Map.Entry<Timestep, List<Object>> entry : table.entrySet()) {
      result
          .put(entry.getKey(), Evidence.constructAndCompile(entry.getValue()));
    }
    return result;
  }

  /**
   * Split queries by the timestep they refer to.
   * Atemporal queries are assigned to timestep null.
   */
  public static Map<Timestep, List<Query>> splitQueriesInTime(
      List<Query> queries) {
    Map<Timestep, List<Query>> table = new HashMap<Timestep, List<Query>>();
    for (Query q : queries) {
      Timestep t = ((ArgSpecQuery) q).argSpec().maxTimestep();
      List<Query> qs = table.get(t);
      if (qs == null) {
        qs = new LinkedList<Query>();
        table.put(t, qs);
      }
      qs.add(q);
    }
    return table;
  }

  /**
   * Return all evidence up to and including the given timestep index.
   */
  public static Evidence getEvidenceUpTo(int timestepIndex, Evidence evidence) {
    Map<Timestep, Evidence> splitEvidence = splitEvidenceInTime(evidence);
    final Evidence result = new Evidence();
    for (Map.Entry<Timestep, Evidence> entry : splitEvidence.entrySet()) {
      if (entry.getKey().intValue() <= timestepIndex) {
        result.addAll(entry.getValue());
      }
    }
    return result;
  }
}

@@ -38,34 +38,8 @@
 ap;%0A
-import java.util.HashSet;%0A
 impo
@@ -57,24 +57,24 @@
 l.Iterator;%0A
+
 import java.
@@ -165,73 +165,8 @@
 ar;%0A
-import blog.bn.BayesNetVar;%0Aimport blog.common.FilteredIterator;%0A
 impo
@@ -225,33 +225,8 @@
 ce;%0A
-import blog.model.Model;%0A
 impo
@@ -680,1759 +680,8 @@
 l %7B%0A
-  /**%0A   * Returns a string obtained by replacing all identifiers %3Ccode%3Et%3C/code%3E in a%0A   * given string by the string representation of a timestep the index of which%0A   * is given.%0A   */%0A  public static String replaceTByTimeStep(String string, int timestepIndex) %7B%0A    return string.replaceAll(%22%5C%5Cbt%5C%5Cb%22, %22@%22 + timestepIndex);%0A  %7D%0A%0A  /**%0A   * Returns the query obtained by instantiating a query string with a given%0A   * time step.%0A   */%0A  public static ArgSpecQuery getQueryForTimestep(String queryString,%0A      Model model, int timestepIndex) %7B%0A    String queryForLastestTimestepString = DBLOGUtil.replaceTByTimeStep(%0A        queryString, timestepIndex);%0A    ArgSpecQuery query = BLOGUtil.parseQuery_NE(%22query %22%0A        + queryForLastestTimestepString + %22;%22, model);%0A    return query;%0A  %7D%0A%0A  /**%0A   * An iterator over the time step indices present in a partial world.%0A   */%0A  public static class TimestepIndicesIterator extends FilteredIterator %7B%0A    public TimestepIndicesIterator(PartialWorld world) %7B%0A      super(world.getInstantiatedVars().iterator());%0A    %7D%0A%0A    public Object filter(int index, Object varObj) %7B%0A      BayesNetVar var = (BayesNetVar) varObj;%0A      int timestepIndex = var.maxTimestep().getValue();%0A      if (timestepIndex %3C 0 %7C%7C alreadyReturned.contains(timestepIndex)) %7B%0A        // Don't want to return the same timestep twice.%0A        return null;%0A      %7D%0A      alreadyReturned.add(timestepIndex);%0A      return timestepIndex;%0A    %7D%0A%0A    private HashSet%3CInteger%3E alreadyReturned = new HashSet%3CInteger%3E();%0A  %7D%0A%0A  /**%0A   * Returns an iterator over the time step indices present in a partial world.%0A   */%0A  public static Iterator getTimestepIndicesIterator(PartialWorld world) %7B%0A    return new TimestepIndicesIterator(world);%0A  %7D%0A%0A
   /*
@@ -3231,32 +3231,32 @@
 s.add(q);%0A    %7D%0A
+
     return table
@@ -3264,500 +3264,7 @@
 %0A  %7D
-%0A%0A  /**%0A   * Return all evidence up to and including the given timestep index.%0A   */%0A  public static Evidence getEvidenceUpTo(int timestepIndex, Evidence evidence) %7B%0A    Map%3CTimestep, Evidence%3E splitEvidence = splitEvidenceInTime(evidence);%0A    final Evidence result = new Evidence();%0A    for (Map.Entry%3CTimestep, Evidence%3E entry : splitEvidence.entrySet()) %7B%0A      if (entry.getKey().intValue() %3C= timestepIndex) %7B%0A        result.addAll(entry.getValue());%0A      %7D%0A    %7D%0A    return result;%0A  %7D
 %0A%7D%0A

remove DBLOGUtil methods that are no longer used anywhere