/*
 * Copyright 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.gwt.junit;

import com.google.gwt.dev.cfg.BindingProperty;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.Properties;
import com.google.gwt.dev.util.Util;
import com.google.gwt.junit.JUnitShell.Strategy;
import com.google.gwt.junit.client.WithProperties;
import com.google.gwt.junit.client.WithProperties.Property;

import junit.framework.TestCase;

import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;

/**
 * A {@link JUnitShell.Strategy} that will alter the module the tests are run
 * in by defining module properties as requested by annotations on the tests.
 */
public class PropertyDefiningStrategy implements Strategy {
  private TestCase testCase;
  private Set<Property> properties;

  public PropertyDefiningStrategy(TestCase testCase) {
    this.testCase = testCase;
  }

  @Override
  public String getSyntheticModuleExtension() {
    String extension = "JUnit";
    computePropertiesMap();
    if (properties.size() > 0) {
      StringBuilder sb = new StringBuilder();
      for (Property property : properties) {
        sb.append(".").append(property.name()).append(
            "_").append(property.value());
      }
      extension += sb.toString();
    }
    return extension;
  }

  @Override
  public void processModule(ModuleDef module) {
    computePropertiesMap();
    if (properties.size() > 0) {
      Properties props = module.getProperties();
      for (Property property : properties) {
        BindingProperty binding = props.createBinding(property.name());
        if (!binding.isDefinedValue(property.value())) {
          binding.addTargetLibraryDefinedValue(binding.getRootCondition(), property.value());
        }
        binding.setAllowedValues(
            binding.getRootCondition(), property.value());
      }
    }
  }

  private Property checkProperty(Property property) {
    String[] tokens = (property.name() + ". ").split("\\.");
    for (int i = 0; i < tokens.length - 1; i++) {
      if (!Util.isValidJavaIdent(tokens[i])) {
        throw new AssertionError(
            "Property name invalid: " + property.name());
      }
    }

    if (!Util.isValidJavaIdent(property.value())) {
      throw new AssertionError(
          "Property value invalid: " + property.value());
    }

    return property;
  }

  private void computePropertiesMap() {
    if (properties == null) {
      Set<Property> props = new TreeSet<Property>(
          new Comparator<Property>() {
        public int compare(Property p1, Property p2) {
          int r = p1.name().compareTo(p2.name());
          if (r == 0) {
            r = p1.value().compareTo(p2.value());
          }
          return r;
        }
      });
      try {
        String name = testCase.getName();
        if (name != null) {
          Method testMethod = testCase.getClass().getMethod(testCase.getName());
          if (testMethod.isAnnotationPresent(WithProperties.class)) {
            WithProperties annotation =
              testMethod.getAnnotation(WithProperties.class);
            for (Property property : annotation.value()) {
              props.add(checkProperty(property));
            }
          }
        }
      } catch (SecurityException e) {
        // should not happen
        e.printStackTrace();
      } catch (NoSuchMethodException e) {
        // should not happen
        e.printStackTrace();
      }
      properties = props;
    }
  }
}
