package com.squarespace.template;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;

import org.apache.commons.io.IOUtils;
import org.testng.annotations.Test;

import com.squarespace.v6.utils.JSONUtils;


public class TokenizerPerfTest extends UnitTestBase {

  private static final double NANOSECONDS = 1_000_000.0;
  
  private String expand(String data, int times) {
    StringBuilder buf = new StringBuilder();
    for (int i = 0; i < times; i++) {
      buf.append(data);
    }
    return buf.toString();
  }
  
  @Test
  public void testSpeed() throws Exception {
    Thread.sleep(1);
    String data = "START {foo.bar} {.section foo}{bar} {d|date %c} {.repeated section list}A{@}{.end}{.end} END-";
    String jsonData = "{\"foo\": {\"bar\": 123}, \"d\": 1368160997000, \"list\": [1, 2, 3, 4, 5]}";
    for (int i = 2; i < (256 * 128); i *= 2 ) {
      String testData = expand(data, i);
      run(testData, jsonData);
    }
  }
  
  @Test
  public void testStatic() throws Exception {
    String template = read("/Users/phensley/jsont_testcases/adirondack-demo_35.html");
    String json = read("/Users/phensley/jsont_testcases/adirondack-demo_35.json");
    for (int i = 2; i < 10; i++) {
      template += template;
      run(template, json);
    }
  }
  
  private String read(String path) throws IOException {
    try (InputStream input = Files.newInputStream(Paths.get(path))) {
      return IOUtils.toString(input);
    }
  }
  
  private void run(String data, String jsonData) throws CodeException {
    JsonTemplateEngine compiler = compiler();
    String result = null;
    int iters = 20;
    double[] times = new double[iters];
    for (int i = 0; i < iters; i++) {
      long start = System.nanoTime();
      CompiledTemplate script = compiler.compile(data);
      long compileTime = System.nanoTime() - start;
      
      start = System.nanoTime();
      Context ctx = compiler.execute(script.getCode(), JSONUtils.decode(jsonData));
      result = ctx.buffer().toString();
      long executeTime = System.nanoTime() - start;
      
      times[i] = (compileTime + executeTime) / NANOSECONDS;
    }
    System.out.printf("input        %s chars\n", commas(data.length()));
    System.out.printf("output       %s chars\n",  commas(result.length()));
    
    Arrays.sort(times);
    System.out.printf("execute times (ms):\n\n");
    System.out.printf("   %10.2f  lo\n            ...\n", times[0]);
    for (int i = 8; i < 13; i++) {
      System.out.printf("   %10.2f  %d\n", times[i], i);
    }
    System.out.printf("            ...\n   %10.2f  hi\n", times[iters-1]);
    System.out.println("\n---------------------------------------");
    
  }
  
}

@@ -1705,33 +1705,111 @@
 e%5B%5D 
-times = new double%5Biters%5D
+compTimes = new double%5Biters%5D;%0A    double%5B%5D execTimes = new double%5Biters%5D;%0A    int instructionCount = 0
 ;%0A  
@@ -1934,24 +1934,92 @@
 pile(data);%0A
+      instructionCount = script.getMachine().getInstructionCount();%0A
       long c
@@ -2287,17 +2287,21 @@
  %0A      
-t
+compT
 imes%5Bi%5D 
@@ -2302,17 +2302,16 @@
 es%5Bi%5D = 
-(
 compileT
@@ -2314,17 +2314,51 @@
 ileTime 
-+
+/ NANOSECONDS;%0A      execTimes%5Bi%5D =
  execute
@@ -2361,17 +2361,16 @@
 cuteTime
-)
  / NANOS
@@ -2540,26 +2540,120 @@
     
-%0A    Arrays.sort(t
+System.out.printf(%22instructions %25d%5Cn%22, instructionCount);%0A    %0A    Arrays.sort(compTimes);%0A    Arrays.sort(execT
 imes
@@ -2682,16 +2682,26 @@
 tf(%22
+compile + 
 execute 
 time
@@ -2696,21 +2696,23 @@
 execute 
-times
+= total
  (ms):%5Cn
@@ -2740,26 +2740,41 @@
 printf(%22   %25
-10
+8.2f + %258.2f = %258
 .2f  lo%5Cn   
@@ -2794,17 +2794,73 @@
 n%22, 
-t
+compTimes%5B0%5D, execTimes%5B0%5D,%0A        (compTimes%5B0%5D + execT
 imes%5B0%5D)
 ;%0A  
@@ -2855,16 +2855,17 @@
 imes%5B0%5D)
+)
 ;%0A    fo
@@ -2889,24 +2889,74 @@
  13; i++) %7B%0A
+      double total = compTimes%5Bi%5D + execTimes%5Bi%5D;%0A
       System
@@ -2968,26 +2968,41 @@
 printf(%22   %25
-10
+8.2f + %258.2f = %258
 .2f  %25d%5Cn%22, 
@@ -3005,17 +3005,21 @@
 n%22, 
-t
+compT
 imes%5Bi%5D,
  i);
@@ -3014,16 +3014,37 @@
 imes%5Bi%5D,
+ execTimes%5Bi%5D, total,
  i);%0A   
@@ -3094,36 +3094,126 @@
    %25
-10.2f  hi%5Cn%22, times%5Biters-1%5D
+8.2f + %258.2f = %258.2f  hi%5Cn%22, compTimes%5Biters-1%5D, execTimes%5Biters-1%5D,%0A        (compTimes%5Biters-1%5D + execTimes%5Biters-1%5D)
 );%0A 

Split perf test to show compile/execute times.