/*
 * Copyright (C) 2012 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.runner;

import com.google.caliper.bridge.CommandLineSerializer;
import com.google.caliper.bridge.OpenedSocket;
import com.google.caliper.bridge.WorkerSpec;
import com.google.caliper.config.VmConfig;
import com.google.caliper.model.BenchmarkSpec;
import com.google.caliper.runner.Instrument.Instrumentation;
import com.google.caliper.worker.WorkerMain;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ListenableFuture;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.logging.Logger;

import javax.annotation.concurrent.GuardedBy;
import javax.inject.Inject;

/**
 * A representation of an unstarted worker.
 *
 * <p>A worker is a sub process that runs a benchmark trial.  Specifically it is a JVM running
 * {@link com.google.caliper.worker.WorkerMain}.  Because of this we can make certain assumptions
 * about its behavior, including but not limited to:
 *
 * <ul>
 *   <li>The worker will connect back to us over a socket connection and send us UTF-8 json
 *       messages in a line oriented protocol.
 *   <li>TODO(lukes,gak): This is probably as good a place as any to specify the entire protocol.
 * </ul>
 */
@TrialScoped final class WorkerProcess {
  private static final Logger logger = Logger.getLogger(WorkerProcess.class.getName());

  @GuardedBy("this")
  private Process worker;
  private final ProcessBuilder workerBuilder;
  private final ShutdownHookRegistrar shutdownHookRegistrar;
  private final ListenableFuture<OpenedSocket> openedSocket;
  private final UUID trialId;

  @VisibleForTesting WorkerProcess(ProcessBuilder workerBuilder,
      UUID trialId,
      ListenableFuture<OpenedSocket> openedSocket,
      ShutdownHookRegistrar shutdownHookRegistrar) {
    this.trialId = trialId;
    this.workerBuilder = workerBuilder;
    this.openedSocket = openedSocket;
    this.shutdownHookRegistrar = shutdownHookRegistrar;
  }

  @Inject WorkerProcess(@TrialId UUID trialId,
      ListenableFuture<OpenedSocket> openedSocket,
      Experiment experiment,
      BenchmarkSpec benchmarkSpec,
      @LocalPort int localPort,
      BenchmarkClass benchmarkClass,
      ShutdownHookRegistrar shutdownHookRegistrar) {
    this.trialId = trialId;
    this.workerBuilder =
        buildProcess(trialId, experiment, benchmarkSpec, localPort, benchmarkClass);
    this.openedSocket = openedSocket;
    this.shutdownHookRegistrar = shutdownHookRegistrar;
  }

  ListenableFuture<OpenedSocket> socketFuture() {
    return openedSocket;
  }

  /**
   * Returns a {@link Process} representing this worker.  The process will be started if it hasn't
   * already.
   */
  synchronized Process startWorker() throws IOException {
    if (worker == null) {
      final Process delegate = workerBuilder.start();
      final Thread shutdownHook = new Thread("worker-shutdown-hook-" + trialId) {
        @Override public void run() {
          delegate.destroy();
        }
      };
      shutdownHookRegistrar.addShutdownHook(shutdownHook);
      worker = new Process() {
        @Override public OutputStream getOutputStream() {
          return delegate.getOutputStream();
        }

        @Override public InputStream getInputStream() {
          return delegate.getInputStream();
        }

        @Override public InputStream getErrorStream() {
          return delegate.getErrorStream();
        }

        @Override public int waitFor() throws InterruptedException {
          int waitFor = delegate.waitFor();
          shutdownHookRegistrar.removeShutdownHook(shutdownHook);
          return waitFor;
        }

        @Override public int exitValue() {
          int exitValue = delegate.exitValue();
          // if it hasn't thrown, the process is done
          shutdownHookRegistrar.removeShutdownHook(shutdownHook);
          return exitValue;
        }

        @Override public void destroy() {
          delegate.destroy();
          shutdownHookRegistrar.removeShutdownHook(shutdownHook);
        }
      };
    }
    return worker;
  }
  
  @VisibleForTesting static ProcessBuilder buildProcess(
      UUID trialId,
      Experiment experiment,
      BenchmarkSpec benchmarkSpec,
      int localPort,
      BenchmarkClass benchmarkClass) {
    // TODO(lukes): it would be nice to split this method into a few smaller more targeted methods
    Instrumentation instrumentation = experiment.instrumentation();
    Instrument instrument = instrumentation.instrument();
    WorkerSpec request = new WorkerSpec(
        trialId,
        instrumentation.workerClass(),
        instrumentation.workerOptions(),
        benchmarkSpec,
        ImmutableList.copyOf(instrumentation.benchmarkMethod.getParameterTypes()),
        localPort);

    ProcessBuilder processBuilder = new ProcessBuilder().redirectErrorStream(false);

    List<String> args = processBuilder.command();

    VirtualMachine vm = experiment.vm();
    VmConfig vmConfig = vm.config;
    args.addAll(getJvmArgs(vm, benchmarkClass));

    Iterable<String> instrumentJvmOptions = instrument.getExtraCommandLineArgs(vmConfig);
    logger.fine(String.format("Instrument(%s) Java args: %s", instrument.getClass().getName(),
        instrumentJvmOptions));
    Iterables.addAll(args, instrumentJvmOptions);

    // last to ensure that they're always applied
    args.addAll(vmConfig.workerProcessArgs());

    args.add(WorkerMain.class.getName());
    args.add(CommandLineSerializer.render(request));

    logger.finest(String.format("Full JVM (%s) args: %s", vm.name, args));
    return processBuilder;
  }
  
  @VisibleForTesting static List<String> getJvmArgs(
      VirtualMachine vm,
      BenchmarkClass benchmarkClass) {

    VmConfig vmConfig = vm.config;
    String platformName = vmConfig.platformName();

    List<String> args = Lists.newArrayList();
    String jdkPath = vmConfig.vmExecutable().getAbsolutePath();
    args.add(jdkPath);
    logger.fine(String.format("%s(%s) Path: %s", platformName, vm.name, jdkPath));

    ImmutableList<String> jvmOptions = vmConfig.options();
    args.addAll(jvmOptions);
    logger.fine(String.format("%s(%s) args: %s", platformName, vm.name, jvmOptions));
    
    ImmutableSet<String> benchmarkJvmOptions = benchmarkClass.vmOptions();
    args.addAll(benchmarkJvmOptions);
    logger.fine(String.format("Benchmark(%s) %s args: %s", benchmarkClass.name(), platformName,
        benchmarkJvmOptions));

    ImmutableList<String> classPathArgs = vmConfig.workerClassPathArgs();
    args.addAll(classPathArgs);
    logger.finer(String.format("Class path args: %s", classPathArgs));

    // TODO(iam): consider forwarding -Djava.library.path= for JNI library support.
    return args;
  }
}
