/*
 * Copyright (C) 2010 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.AbstractBenchmarkException;
import com.google.caliper.UserException.DoesntImplementBenchmarkException;
import com.google.caliper.UserException.ExceptionFromUserCodeException;
import com.google.caliper.UserException.NoParameterlessConstructorException;
import com.google.caliper.UserException.NoSuchClassException;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * Figures out which scenarios to benchmark given a benchmark suite, set of user
 * parameters, and set of user VMs.
 */
public final class ScenarioSelection {

  private final String suiteClassName;
  private final Multimap<String, String> userParameters;
  private final Set<String> userVms;

  private Benchmark suite;

  /** Effective parameters to run in the benchmark. */
  private final Multimap<String, String> parameters = LinkedHashMultimap.create();

  public ScenarioSelection(Arguments arguments) {
    this(arguments.getSuiteClassName(), arguments.getUserParameters(), arguments.getUserVms());
  }

  public ScenarioSelection(String suiteClassName,
      Multimap<String, String> userParameters, Set<String> userVms) {
    this.suiteClassName = suiteClassName;
    this.userParameters = userParameters;
    this.userVms = userVms;
  }

  /**
   * Returns the selected scenarios for this benchmark.
   */
  public List<Scenario> select() {
    prepareSuite();
    prepareParameters();
    return createScenarios();
  }

  public TimedRunnable createBenchmark(Scenario scenario) {
    return suite.createBenchmark(scenario.getParameters());
  }

  private void prepareSuite() {
    Class<?> benchmarkClass;
    try {
      benchmarkClass = getClassByName(suiteClassName);
    } catch (ExceptionInInitializerError e) {
      throw new ExceptionFromUserCodeException(e.getCause());
    } catch (ClassNotFoundException ignored) {
      throw new NoSuchClassException(suiteClassName);
    }

    Object s;
    try {
      Constructor<?> constructor = benchmarkClass.getDeclaredConstructor();
      constructor.setAccessible(true);
      s = constructor.newInstance();
    } catch (InstantiationException ignore) {
      throw new AbstractBenchmarkException(benchmarkClass);
    } catch (NoSuchMethodException ignore) {
      throw new NoParameterlessConstructorException(benchmarkClass);
    } catch (IllegalAccessException impossible) {
      throw new AssertionError(impossible); // shouldn't happen since we setAccessible(true)
    } catch (InvocationTargetException e) {
      throw new ExceptionFromUserCodeException(e.getCause());
    }

    if (s instanceof Benchmark) {
      this.suite = (Benchmark) s;
    } else {
      throw new DoesntImplementBenchmarkException(benchmarkClass);
    }
  }

  private static Class<?> getClassByName(String className) throws ClassNotFoundException {
    try {
      return Class.forName(className);
    } catch (ClassNotFoundException ignored) {
      // try replacing the last dot with a $, in case that helps
      // example: tutorial.Tutorial.Benchmark1 becomes tutorial.Tutorial$Benchmark1
      // amusingly, the $ character means three different things in this one line alone
      String newName = className.replaceFirst("\\.([^.]+)$", "\\$$1");
      return Class.forName(newName);
    }
  }

  private void prepareParameters() {
    for (String key : suite.parameterNames()) {
      // first check if the user has specified values
      Collection<String> userValues = userParameters.get(key);
      if (!userValues.isEmpty()) {
        parameters.putAll(key, userValues);
        // TODO: type convert 'em to validate?

      } else { // otherwise use the default values from the suite
        Set<String> values = suite.parameterValues(key);
        if (values.isEmpty()) {
          throw new ConfigurationException(key + " has no values");
        }
        parameters.putAll(key, values);
      }
    }
  }

  private ImmutableSet<String> defaultVms() {
    return "Dalvik".equals(System.getProperty("java.vm.name"))
        ? ImmutableSet.of("dalvikvm")
        : ImmutableSet.of("java");
  }

  /**
   * Returns a complete set of scenarios with every combination of values and
   * benchmark classes.
   */
  private List<Scenario> createScenarios() {
    List<ScenarioBuilder> builders = new ArrayList<ScenarioBuilder>();

    // create scenarios for each VM
    Set<String> vms = userVms.isEmpty()
        ? defaultVms()
        : userVms;
    for (String vm : vms) {
      ScenarioBuilder scenarioBuilder = new ScenarioBuilder();
      scenarioBuilder.parameters.put(Scenario.VM_KEY, vm);
      builders.add(scenarioBuilder);
    }

    for (Entry<String, Collection<String>> parameter : parameters.asMap().entrySet()) {
      Iterator<String> values = parameter.getValue().iterator();
      if (!values.hasNext()) {
        throw new ConfigurationException("Not enough values for " + parameter);
      }

      String key = parameter.getKey();

      String firstValue = values.next();
      for (ScenarioBuilder builder : builders) {
        builder.parameters.put(key, firstValue);
      }

      // multiply the size of the specs by the number of alternate values
      int size = builders.size();
      while (values.hasNext()) {
        String alternate = values.next();
        for (int s = 0; s < size; s++) {
          ScenarioBuilder copy = builders.get(s).copy();
          copy.parameters.put(key, alternate);
          builders.add(copy);
        }
      }
    }

    List<Scenario> result = new ArrayList<Scenario>();
    for (ScenarioBuilder builder : builders) {
      result.add(builder.build());
    }

    return result;
  }

  private static class ScenarioBuilder {
    final Map<String, String> parameters = new LinkedHashMap<String, String>();

    ScenarioBuilder copy() {
      ScenarioBuilder result = new ScenarioBuilder();
      result.parameters.putAll(parameters);
      return result;
    }

    public Scenario build() {
      return new Scenario(parameters);
    }
  }
}
