package hex;

import water.H2O;
import water.Key;
import water.Request2;
import water.UKV;
import water.api.DocGen;
import water.fvec.CreateInteractions;
import water.fvec.Frame;
import water.util.Log;
import water.util.RString;


/**
 * Create new factors that represent interactions of the given factors
 */
public class Interaction extends Request2 {
  static final int API_WEAVER=1; // This file has auto-gen'd doc & json fields
  static public DocGen.FieldDoc[] DOC_FIELDS; // Initialized from Auto-Gen code.

  @API(help = "Input data frame", required = true, filter = Default.class, json=true)
  public Frame source;

  @API(help = "Output data frame", required = true, filter = Default.class, json=true)
  public String target;

  @API(help = "Column indices (0-based) of factors for which interaction is to be computed", filter=colsNamesIdxFilter.class, displayName="Interaction columns")
  public int[] factors = new int[0];
  class colsNamesIdxFilter extends MultiVecSelect { public colsNamesIdxFilter() {super("source", MultiVecSelectType.NAMES_THEN_INDEXES); } }

  @API(help = "Max. number of factor levels in pair-wise interaction terms (if enforced, one extra catch-all factor will be made)", required = true, filter = Default.class, lmin = 1, lmax = Integer.MAX_VALUE, json=true)
  public int max_factors = 100;

  @API(help = "Min. occurrence threshold for factor levels in pair-wise interaction terms", required = true, filter = Default.class, lmin = 1, lmax = Integer.MAX_VALUE, json=true)
  public int min_occurrence = 1;

  @Override public Response serve() {
    try {
//      if (max_factors < 1) throw new IllegalArgumentException("max_factors must be >1.");
      if (factors.length == 0) throw new IllegalArgumentException("factors must be non-empty.");
      for (int v: factors) {
        if (!source.vecs()[v].isEnum()) {
          throw new IllegalArgumentException("Column " + source.names()[v] + " is not a factor.");
        }
      }

      final CreateInteractions in = new CreateInteractions(this);
      H2O.submitTask(in);
      in.join();

      Log.info("Created frame '" + target + "'.");
      return Response.done(this);
    } catch( Throwable t ) {
      return Response.error(t);
    }
  }

  @Override public boolean toHTML( StringBuilder sb ) {
    Frame fr = UKV.get(Key.make(target));
    if (fr==null) {
      return false;
    }
    RString aft = new RString("<a href='Inspect2.html?src_key=%$key'>%key</a>");
    aft.replace("key", target);
    DocGen.HTML.section(sb, "Feature generation done.<br/>Frame '" + aft.toString() + "' now has " + fr.numCols() + " columns.");
    return true;
  }

}

@@ -18,58 +18,42 @@
 ort 
-water.H2O;%0Aimport water.Key;%0Aimport water.Request2
+org.codehaus.jackson.PrettyPrinter
 ;%0Aim
@@ -63,19 +63,17 @@
 t water.
-UKV
+*
 ;%0Aimport
@@ -1519,16 +1519,31 @@
 e = 1;%0A%0A
+  long _time;%0A%0A
   @Overr
@@ -1960,16 +1960,48 @@
      %7D%0A%0A
+      Timer time = new Timer();%0A
       fi
@@ -2105,57 +2105,58 @@
 ();%0A
-%0A      Log.info(%22Created frame '%22 + target + %22'.%22
+      _time = time.time();%0A      Log.info(report()
 );%0A 
@@ -2549,33 +2549,20 @@
 sb, 
-%22Feature generation done.
+report() + %22
 %3Cbr/
@@ -2656,10 +2656,320 @@
 e;%0A  %7D%0A%0A
+  private String report() %7B%0A    Frame res = UKV.get(Key.make(target));%0A    return %22Created interaction feature %22 + res.names()%5Bsource.numCols()%5D%0A            + %22 (order: %22 + factors.length + %22) with %22 + res.lastVec().domain().length + %22 factor levels%22%0A            + %22 in%22 + PrettyPrint.msecs(_time, true);%0A  %7D%0A%0A
 %7D%0A

Add timing info.