package com.iscsuwpp;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.Scanner;


public class NashornEngineTester extends ThreadPoolExecutor {

  //static ScriptEngineManager factory = new ScriptEngineManager();
  //static ScriptEngine engine = factory.getEngineByName("JavaScript");
  static String space1000 = " ".repeat(1000);

  public NashornEngineTester(int corePoolSize, int maximumPoolSize,
                                 long keepAliveTime, TimeUnit unit,
                                 BlockingQueue<Runnable> workQueue) {
    super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
  }

  @Override
  protected void beforeExecute(Thread t, Runnable r) {
    super.beforeExecute(t, r);
    ((Task)r).startTime = System.nanoTime();
  }

  @Override
  protected void afterExecute(Runnable r, Throwable t) {
    super.afterExecute(r, t);
    long endTime = System.nanoTime();
    long duration = endTime - ((Task)r).startTime;
    // Format the timestamp
    LocalDateTime now = LocalDateTime.now();
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    String formattedDateTime = now.format(formatter);

    OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
    System.out.println(formattedDateTime + " "  + Thread.currentThread().getName() + " " + ((Task)r).value.toString() + " Total # of Processors " + osBean.getAvailableProcessors()+ ". Time: " + duration/1000000 + " ms");

  }

  private static class Task implements Runnable {
    long startTime;
    Object value;

    @Override
    public void run() {
      ScriptEngineManager factory = new ScriptEngineManager();
      ScriptEngine engine = factory.getEngineByName("JavaScript");
      try {
        value = engine.eval("('1' == '2');");
      } catch (ScriptException e) {
        throw new RuntimeException(e);
      }
    }
  }

  // java -XX:ActiveProcessorCount=1 -Dnashorn.args="--log=classcache:finest,codestore:finest " -classpath /libs/*:. com.iscsuwpp.NashornEngineTester 4 200
  public static void main(String[] args) {
    int numberOfThreads = Integer.parseInt(args[0]);
    int numberOfTasks = Integer.parseInt(args[1]);

    // wait until profiler is atached to this process
    Scanner scanner = new Scanner(System.in);
    System.out.println("Press Enter to continue...");
    scanner.nextLine();
    scanner.close();


    NashornEngineTester executor = new NashornEngineTester(
        numberOfThreads/2, numberOfThreads, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>());

    for (int i = 0; i < numberOfTasks; i++) {
      executor.execute(new Task());
    }

    executor.shutdown();
  }
}
