/*
 * Copyright (C) 2009 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.caliper;

import com.google.caliper.UserException.DisplayUsageException;
import com.google.caliper.UserException.ExceptionFromUserCodeException;
import com.google.caliper.util.InterleavedReader;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ObjectArrays;
import com.google.common.io.Closeables;
import com.google.gson.JsonObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TimeZone;
import java.util.regex.Pattern;

/**
 * Creates, executes and reports benchmark runs.
 */
public final class Runner {

  private static final FileFilter UPLOAD_FILE_FILTER = new FileFilter() {
    @Override public boolean accept(File file) {
      return file.getName().endsWith(".xml") || file.getName().endsWith(".json");
    }
  };

  private static final String FILE_NAME_DATE_FORMAT = "yyyy-MM-dd'T'HH-mm-ssZ";

  private static final Splitter ARGUMENT_SPLITTER
      = Splitter.on(Pattern.compile("\\s+")).omitEmptyStrings();

  /** Command line arguments to the process */
  private Arguments arguments;
  private ScenarioSelection scenarioSelection;

  private String createFileName(Result result) {
    String timestamp = createTimestamp();
    return String.format("%s.%s.json", result.getRun().getBenchmarkName(), timestamp);
  }

  private String createTimestamp() {
    SimpleDateFormat dateFormat = new SimpleDateFormat(FILE_NAME_DATE_FORMAT, Locale.US);
    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
    dateFormat.setLenient(true);
    return dateFormat.format(new Date());
  }

  public void run(String... args) {
    this.arguments = Arguments.parse(args);
    File resultsUploadFile = arguments.getUploadResultsFile();
    if (resultsUploadFile != null) {
      uploadResultsFileOrDir(resultsUploadFile);
      return;
    }
    this.scenarioSelection = new ScenarioSelection(arguments);
    if (arguments.getDebug()) {
      debug();
      return;
    }
    Result result = runOutOfProcess();
    new ConsoleReport(result.getRun(), arguments).displayResults();
    boolean saveResultsLocally = arguments.getSaveResultsFile() != null;
    try {
      postResults(result);
    } catch (Exception e) {
      System.out.println();
      System.out.println(e);
      saveResultsLocally = true;
    }

    if (saveResultsLocally) {
      saveResults(result);
    }
  }

  void uploadResultsFileOrDir(File resultsFileOrDir) {
    try {
      if (resultsFileOrDir.isDirectory()) {
        for (File resultsFile : resultsFileOrDir.listFiles(UPLOAD_FILE_FILTER)) {
          uploadResults(resultsFile);
        }
      } else {
        uploadResults(resultsFileOrDir);
      }
    } catch (Exception e) {
      throw new RuntimeException("uploading XML file failed", e);
    }
  }

  private void uploadResults(File resultsUploadFile) throws IOException {
    System.out.println();
    System.out.println("Uploading " + resultsUploadFile.getCanonicalPath());
    InputStream inputStream = new FileInputStream(resultsUploadFile);
    try {
      Result result = new ResultsReader().getResult(inputStream);
      postResults(result);
    } finally {
      inputStream.close();
    }
  }

  private void saveResults(Result result) {
    File resultsFile = arguments.getSaveResultsFile();
    File destinationFile;
    if (resultsFile == null) {
      File dir = new File("./caliper-results");
      dir.mkdirs();
      destinationFile = new File(dir, createFileName(result));
    } else if (resultsFile.exists() && resultsFile.isDirectory()) {
      destinationFile = new File(resultsFile, createFileName(result));
    } else {
      // assume this is a file
      File parent = resultsFile.getParentFile();
      if (parent != null) {
        parent.mkdirs();
      }
      destinationFile = resultsFile;
    }

    PrintStream filePrintStream;
    try {
      filePrintStream = new PrintStream(new FileOutputStream(destinationFile));
    } catch (FileNotFoundException e) {
      throw new RuntimeException("can't open " + destinationFile, e);
    }
    String resultJson = Json.getGsonInstance().toJson(result);
    try {
      System.out.println();
      System.out.println("Writing results to " + destinationFile.getCanonicalPath());
      filePrintStream.print(resultJson);
    } catch (Exception e) {
      System.out.println(e);
      System.out.println("Failed to write results to file, writing to standard out instead:");
      System.out.println(resultJson);
      System.out.flush();
    } finally {
      filePrintStream.close();
    }
  }

  private void postResults(Result result) {
    CaliperRc caliperrc = CaliperRc.INSTANCE;
    String postUrl = caliperrc.getPostUrl();
    String apiKey = caliperrc.getApiKey();
    if (postUrl == null || apiKey == null) {
      // TODO: probably nicer to show a message if only one is null
      return;
    }

    try {
      URL url = new URL(postUrl + apiKey + "/" + result.getRun().getBenchmarkName());
      HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(getProxy());
      urlConnection.setDoOutput(true);
      String resultJson = Json.getGsonInstance().toJson(result);
      urlConnection.getOutputStream().write(resultJson.getBytes());
      if (urlConnection.getResponseCode() == 200) {
        System.out.println("");
        System.out.println("View current and previous benchmark results online:");
        BufferedReader in = new BufferedReader(
            new InputStreamReader(urlConnection.getInputStream()));
        System.out.println("  " + in.readLine());
        in.close();
        return;
      }

      System.out.println("Posting to " + postUrl + " failed: "
          + urlConnection.getResponseMessage());
      BufferedReader reader = new BufferedReader(
          new InputStreamReader(urlConnection.getInputStream()));
      String line;
      while ((line = reader.readLine()) != null) {
        System.out.println(line);
      }
      reader.close();
    } catch (IOException e) {
      throw new RuntimeException("Posting to " + postUrl + " failed.", e);
    }
  }

  private Proxy getProxy() {
    String proxyAddress = CaliperRc.INSTANCE.getProxy();
    if (proxyAddress == null) {
      return Proxy.NO_PROXY;
    }

    String[] proxyHostAndPort = proxyAddress.trim().split(":");
    return new Proxy(Proxy.Type.HTTP, new InetSocketAddress(
        proxyHostAndPort[0], Integer.parseInt(proxyHostAndPort[1])));
  }

  private ScenarioResult runScenario(Scenario scenario) {
    MeasurementResult timeMeasurementResult = measure(scenario, MeasurementType.TIME);
    MeasurementSet allocationMeasurements = null;
    String allocationEventLog = null;
    MeasurementSet memoryMeasurements = null;
    String memoryEventLog = null;
    if (arguments.getMeasureMemory()) {
      MeasurementResult allocationsMeasurementResult =
          measure(scenario, MeasurementType.INSTANCE);
      allocationMeasurements = allocationsMeasurementResult.getMeasurements();
      allocationEventLog = allocationsMeasurementResult.getEventLog();
      MeasurementResult memoryMeasurementResult =
          measure(scenario, MeasurementType.MEMORY);
      memoryMeasurements = memoryMeasurementResult.getMeasurements();
      memoryEventLog = memoryMeasurementResult.getEventLog();
    }

    return new ScenarioResult(timeMeasurementResult.getMeasurements(),
        timeMeasurementResult.getEventLog(),
        allocationMeasurements, allocationEventLog,
        memoryMeasurements, memoryEventLog);
  }

  private static class MeasurementResult {
    private final MeasurementSet measurements;
    private final String eventLog;

    MeasurementResult(MeasurementSet measurements, String eventLog) {
      this.measurements = measurements;
      this.eventLog = eventLog;
    }

    public MeasurementSet getMeasurements() {
      return measurements;
    }

    public String getEventLog() {
      return eventLog;
    }
  }

  private MeasurementResult measure(Scenario scenario, MeasurementType type) {
    Vm vm = new VmFactory().createVm(scenario);
    // this must be done before starting the forked process on certain VMs
    ProcessBuilder processBuilder = createCommand(scenario, vm, type)
        .redirectErrorStream(true);
    Process timeProcess;
    try {
      timeProcess = processBuilder.start();
    } catch (IOException e) {
      throw new RuntimeException("failed to start subprocess", e);
    }

    MeasurementSet measurementSet = null;
    StringBuilder eventLog = new StringBuilder();
    InterleavedReader reader = null;
    try {
      reader = new InterleavedReader(arguments.getMarker(),
          new InputStreamReader(timeProcess.getInputStream()));
      Object o;
      while ((o = reader.read()) != null) {
        if (o instanceof String) {
          eventLog.append(o);
        } else if (measurementSet == null) {
          JsonObject jsonObject = (JsonObject) o;
          measurementSet = Json.measurementSetFromJson(jsonObject);
        } else {
          throw new RuntimeException("Unexpected value: " + o);
        }
      }
    } catch (IOException e) {
      throw new RuntimeException(e);
    } finally {
      Closeables.closeQuietly(reader);
      timeProcess.destroy();
    }

    if (measurementSet == null) {
      String message = "Failed to execute " + Joiner.on(" ").join(processBuilder.command());
      System.err.println("  " + message);
      System.err.println(eventLog.toString());
      throw new ConfigurationException(message);
    }

    return new MeasurementResult(measurementSet, eventLog.toString());
  }

  private ProcessBuilder createCommand(Scenario scenario, Vm vm, MeasurementType type) {
    File workingDirectory = new File(System.getProperty("user.dir"));

    String classPath = System.getProperty("java.class.path");
    if (classPath == null || classPath.length() == 0) {
      throw new IllegalStateException("java.class.path is undefined in " + System.getProperties());
    }

    ImmutableList.Builder<String> vmArgs = ImmutableList.builder();
    vmArgs.addAll(ARGUMENT_SPLITTER.split(scenario.getVariables().get(Scenario.VM_KEY)));
    if (type == MeasurementType.INSTANCE || type == MeasurementType.MEMORY) {
      String allocationJarFile = System.getenv("ALLOCATION_JAR");
      vmArgs.add("-javaagent:" + allocationJarFile);
    }
    vmArgs.addAll(vm.getVmSpecificOptions(type, arguments));

    Map<String, String> vmParameters = scenario.getVariables(
        scenarioSelection.getVmParameterNames());
    for (String vmParameter : vmParameters.values()) {
      vmArgs.addAll(ARGUMENT_SPLITTER.split(vmParameter));
    }

    ImmutableList.Builder<String> caliperArgs = ImmutableList.builder();
    caliperArgs.add("--warmupMillis").add(Long.toString(arguments.getWarmupMillis()));
    caliperArgs.add("--runMillis").add(Long.toString(arguments.getRunMillis()));
    caliperArgs.add("--measurementType").add(type.toString());
    caliperArgs.add("--marker").add(arguments.getMarker());

    Map<String,String> userParameters = scenario.getVariables(
        scenarioSelection.getUserParameterNames());
    for (Entry<String, String> entry : userParameters.entrySet()) {
      caliperArgs.add("-D" + entry.getKey() + "=" + entry.getValue());
    }
    caliperArgs.add(arguments.getSuiteClassName());

    return vm.newProcessBuilder(workingDirectory, classPath,
        vmArgs.build(), InProcessRunner.class.getName(), caliperArgs.build());
  }

  private void debug() {
    try {
      int debugReps = arguments.getDebugReps();
      InProcessRunner runner = new InProcessRunner();
      DebugMeasurer measurer = new DebugMeasurer(debugReps);
      for (Scenario scenario : scenarioSelection.select()) {
        System.out.println("running " + debugReps + " debug reps of " + scenario);
        runner.run(scenarioSelection, scenario, measurer);
      }
    } catch (Exception e) {
      throw new ExceptionFromUserCodeException(e);
    }
  }

  private Result runOutOfProcess() {
    Date executedDate = new Date();
    ImmutableMap.Builder<Scenario, ScenarioResult> resultsBuilder = ImmutableMap.builder();

    try {
      List<Scenario> scenarios = scenarioSelection.select();

      int i = 0;
      for (Scenario scenario : scenarios) {
        beforeMeasurement(i++, scenarios.size(), scenario);
        ScenarioResult scenarioResult = runScenario(scenario);
        afterMeasurement(arguments.getMeasureMemory(), scenarioResult);
        resultsBuilder.put(scenario, scenarioResult);
      }
      System.out.println();

      Environment environment = new EnvironmentGetter().getEnvironmentSnapshot();
      return new Result(
          new Run(resultsBuilder.build(), arguments.getSuiteClassName(), executedDate),
          environment);
    } catch (Exception e) {
      throw new ExceptionFromUserCodeException(e);
    }
  }

  private void beforeMeasurement(int index, int total, Scenario scenario) {
    double percentDone = (double) index / total;
    System.out.printf("%2.0f%% %s", percentDone * 100, scenario);
  }

  private void afterMeasurement(boolean memoryMeasured, ScenarioResult scenarioResult) {
    String memoryMeasurements = "";
    if (memoryMeasured) {
      MeasurementSet instanceMeasurementSet =
          scenarioResult.getMeasurementSet(MeasurementType.INSTANCE);
      String instanceUnit =
        ConsoleReport.UNIT_ORDERING.min(instanceMeasurementSet.getUnitNames().entrySet()).getKey();
      MeasurementSet memoryMeasurementSet = scenarioResult.getMeasurementSet(MeasurementType.MEMORY);
      String memoryUnit =
        ConsoleReport.UNIT_ORDERING.min(memoryMeasurementSet.getUnitNames().entrySet()).getKey();
      memoryMeasurements = String.format(", allocated %s%s for a total of %s%s",
          Math.round(instanceMeasurementSet.medianUnits()), instanceUnit,
          Math.round(memoryMeasurementSet.medianUnits()), memoryUnit);
    }

    MeasurementSet timeMeasurementSet = scenarioResult.getMeasurementSet(MeasurementType.TIME);
    String unit =
        ConsoleReport.UNIT_ORDERING.min(timeMeasurementSet.getUnitNames().entrySet()).getKey();
    System.out.printf(" %.2f %s; \u03C3=%.2f %s @ %d trials%s%n", timeMeasurementSet.medianUnits(),
        unit, timeMeasurementSet.standardDeviationUnits(), unit,
        timeMeasurementSet.getMeasurements().size(), memoryMeasurements);
  }

  public static void main(String[] args) {
    try {
      new Runner().run(args);
      System.exit(0); // user code may have leave non-daemon threads behind!
    } catch (DisplayUsageException e) {
      e.display();
      System.exit(0);
    } catch (UserException e) {
      e.display();
      System.exit(1);
    }
  }

  @SuppressWarnings("unchecked") // temporary fakery
  public static void main(Class<? extends Benchmark> suite, String[] args) {
    main(ObjectArrays.concat(args, suite.getName()));
  }
}
