/*
 * Copyright 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.gwt.dev.jjs.impl;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.CompilerContext;
import com.google.gwt.dev.PrecompileTaskOptionsImpl;
import com.google.gwt.dev.cfg.MockModuleDef;
import com.google.gwt.dev.javac.CheckerTestCase;
import com.google.gwt.dev.javac.CompilationState;
import com.google.gwt.dev.javac.CompilationStateBuilder;
import com.google.gwt.dev.javac.testing.impl.MockJavaResource;
import com.google.gwt.dev.javac.testing.impl.MockResourceOracle;
import com.google.gwt.dev.jjs.JavaAstConstructor;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JBlock;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JLocal;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodBody;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JReturnStatement;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.util.arg.SourceLevel;
import com.google.gwt.dev.util.log.AbstractTreeLogger;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
import com.google.gwt.thirdparty.guava.common.base.Function;
import com.google.gwt.thirdparty.guava.common.base.Joiner;
import com.google.gwt.thirdparty.guava.common.base.Predicates;
import com.google.gwt.thirdparty.guava.common.collect.FluentIterable;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.collect.Sets;

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * A useful base class for tests that build JJS ASTs.
 */
public abstract class JJSTestBase extends CheckerTestCase {

  public static final String MAIN_METHOD_NAME = "onModuleLoad";

  /**
   * Finds a field with a type.
   */
  public static JField findField(JDeclaredType type, String fieldName) {
    for (JField field : type.getFields()) {
      if (field.getName().equals(fieldName)) {
        return field;
      }
    }
    return null;
  }

  /**
   * Finds a field by name, e.g. <code>Foo.field</code>.
   */
  public static JField findField(JProgram program, String qualifiedFieldName) {
    int pos = qualifiedFieldName.lastIndexOf('.');
    assertTrue(pos > 0);
    String typeName = qualifiedFieldName.substring(0, pos);
    String fieldName = qualifiedFieldName.substring(pos + 1);
    JDeclaredType type = findDeclaredType(program, typeName);
    JField field = findField(type, fieldName);
    return field;
  }

  /**
   * Find a local variable declared within a JMethod.
   */
  public static JLocal findLocal(JMethod method, final String localName) {
    class LocalVisitor extends JVisitor {
      JLocal found;

      @Override
      public void endVisit(JLocal x, Context ctx) {
        if (x.getName().equals(localName)) {
          found = x;
        }
      }
    }
    LocalVisitor v = new LocalVisitor();
    v.accept(method);
    return v.found;
  }

  public static JMethod findMainMethod(JProgram program) {
    return findMethod(program, MAIN_METHOD_NAME);
  }

  public static JMethod findMethod(JDeclaredType type, String methodNameOrSignature) {
    // Signatures and names never collide (names never have parens but signatures always do).
    for (JMethod method : type.getMethods()) {
      if (method.getSignature().equals(methodNameOrSignature) ||
          method.getName().equals(methodNameOrSignature)) {
        return method;
      }
    }

    return null;
  }

  public static JMethod findMethod(JProgram program, String methodName) {
    int lastDot = methodName.lastIndexOf(".");
    if (lastDot != -1) {
      String className = methodName.substring(0, lastDot);
      JDeclaredType clazz = program.getFromTypeMap(className);
      assertNotNull("Did not find class " + className, clazz);
      return clazz.findMethod(methodName.substring(lastDot + 1), true);
    }
    return findMethod(program.getFromTypeMap("test.EntryPoint"), methodName);
  }

  public static JMethod findQualifiedMethod(JProgram program, String methodName) {
    int pos = methodName.lastIndexOf('.');
    assertTrue(pos > 0);
    String typeName = methodName.substring(0, pos);
    String unqualMethodName = methodName.substring(pos + 1);
    JDeclaredType type = findDeclaredType(program, typeName);
    return findMethod(type, unqualMethodName);
  }

  private static Pattern typeNamePattern = Pattern.compile("([^\\[\\]]*)((?:\\[\\])*)");

  /**
   * Finds a type by name including arrays and primitives.
   */
  public static JType findType(JProgram program, String typeName) {
    Matcher matcher = typeNamePattern.matcher(typeName);
    if (!matcher.matches()) {
      return null;
    }
    String bareName = matcher.group(1);
    int dimensions = matcher.group(2).length() / 2;

    JType type = JPrimitiveType.getType(bareName);
    if (type == null) {
      type = findDeclaredType(program, bareName);
    }

    if (type != null && dimensions > 0) {
      type = program.getOrCreateArrayType(type, dimensions);
    }
    return type;
  }

  /**
   * Finds a declared type by name. The type name may be short, e.g. <code>"Foo"</code>,
   * or fully-qualified, e.g. <code>"com.google.example.Foo"</code>. If a short
   * name is used, it must be unambiguous.
   */
  public static JDeclaredType findDeclaredType(JProgram program, String typeName) {
    JDeclaredType type = program.getFromTypeMap(typeName);
    if (type != null || typeName.indexOf('.') != -1) {
      return type;
    }
    // Do a slow lookup by short name.
    for (JDeclaredType checkType : program.getDeclaredTypes()) {
      if (!checkType.getShortName().equals(typeName)) {
        continue;
      }
      if (type != null) {
        fail("Ambiguous type reference '" + typeName + "' might be '"
            + type.getName() + "' or '" + checkType.getName()
            + "' (possibly more matches)");
      }
      type = checkType;
    }
    return type;
  }

  public static String getMainMethodSource(JProgram program) {
    JMethod mainMethod = findMainMethod(program);
    return mainMethod.getBody().toSource();
  }

  /**
   * Tweak this if you want to see the log output.
   */
  private static TreeLogger createTreeLogger() {
    boolean reallyLog = true;
    if (reallyLog) {
      AbstractTreeLogger logger = new PrintWriterTreeLogger();
      logger.setMaxDetail(TreeLogger.WARN);
      return logger;
    }
    return TreeLogger.NULL;
  }

  protected TreeLogger logger = createTreeLogger();

  protected final MockResourceOracle sourceOracle = new MockResourceOracle();

  private final List<String> snippetClassDecls = Lists.newArrayList();

  private final Set<String> snippetImports = Sets.newTreeSet();

  public JJSTestBase() {
    sourceOracle.add(JavaAstConstructor.getCompilerTypes());
  }

  /**
   * Adds a snippet of code, for example a field declaration, to the class that
   * encloses the snippet subsequently passed to
   * {@link #compileSnippet(String, String, boolean)}.
   */
  protected void addSnippetClassDecl(String...decl) {
    snippetClassDecls.add(Joiner.on("\n").join(decl));
  }

  /**
   * Adds an import statement for any code subsequently passed to
   * {@link #compileSnippet(String, String, boolean)}.
   */
  protected void addSnippetImport(String typeName) {
    snippetImports.add(typeName);
  }

  /**
   * Returns the program that results from compiling the specified code snippet
   * as the body of an entry point method.
   * @param logger a logger where to log, the default logger will be used if null.
   * @param returnType the return type of the method to compile; use "void" if
   *          the code snippet has no return statement
   * @param codeSnippet the body of the entry method
   */
  protected JProgram compileSnippet(TreeLogger logger,  final String returnType,
      final String codeSnippet) throws UnableToCompleteException {
    return compileSnippet(logger, returnType, "", codeSnippet, false);
  }

  /**
   * Returns the program that results from compiling the specified code snippet
   * as the body of an entry point method.
   * @param logger a logger where to log, the default logger will be used if null.
   * @param returnType the return type of the method to compile; use "void" if
   *          the code snippet has no return statement
   * @param codeSnippet the body of the entry method
   * @param staticMethod whether to make the method static
   */
  protected JProgram compileSnippet(TreeLogger logger,  final String returnType,
      final String codeSnippet, boolean staticMethod) throws UnableToCompleteException {
    return compileSnippet(logger, returnType, "", codeSnippet, staticMethod);
  }

  /**
   * Returns the program that results from compiling the specified code snippet
   * as the body of an entry point method.
   * @param returnType the return type of the method to compile; use "void" if
   *          the code snippet has no return statement
   * @param codeSnippet the body of the entry method
   * @param staticMethod whether to make the method static
   */
  protected JProgram compileSnippet(final String returnType,
      final String codeSnippet, boolean staticMethod) throws UnableToCompleteException {
    return compileSnippet(logger, returnType, "", codeSnippet, staticMethod);
  }

  /**
   * Returns the program that results from compiling the specified code snippet
   * as the body of an entry point method.
   * @param returnType the return type of the method to compile; use "void" if
   *          the code snippet has no return statement
   * @param codeSnippet the body of the entry method
   */
  protected JProgram compileSnippet(final String returnType,
      final String codeSnippet) throws UnableToCompleteException {
    return compileSnippet(logger, returnType, "", codeSnippet, false);
  }

  /**
   * Returns the program that results from compiling the specified code snippet
   * as the body of an entry point method.
   *
   * @param logger a logger where to log, the default logger will be used if null.
   * @param returnType the return type of the method to compile; use "void" if
   *          the code snippet has no return statement
   * @param params the parameter list of the method to compile
   * @param codeSnippet the body of the entry method
   * @param staticMethod whether the entryPoint should be static
   */
  protected JProgram compileSnippet(TreeLogger logger, final String returnType,
      final String params, final String codeSnippet, final boolean staticMethod)
      throws UnableToCompleteException {
    sourceOracle.addOrReplace(new MockJavaResource("test.EntryPoint") {
      @Override
      public CharSequence getContent() {
        StringBuilder code = new StringBuilder();
        code.append("package test;\n");
        for (String snippetImport : snippetImports) {
          code.append("import " + snippetImport + ";\n");
        }
        code.append("public class EntryPoint {\n");
        for (String snippetClassDecl : snippetClassDecls) {
          code.append(snippetClassDecl + ";\n");
        }
        code.append("  public " + (staticMethod ? "static " : "") + returnType + " onModuleLoad(" +
            params + ") {\n");
        code.append(codeSnippet);
        code.append("  }\n");
        code.append("}\n");
        return code;
      }
    });
    CompilerContext compilerContext = provideCompilerContext();

    if (logger == null)  {
      logger = this.logger;
    }
    CompilationState state =
        CompilationStateBuilder.buildFrom(logger, compilerContext, sourceOracle.getResources());
    JProgram program =
        JavaAstConstructor.construct(logger, state, compilerContext,
            null, "test.EntryPoint", "com.google.gwt.lang.Exceptions");
    return program;
  }

  /**
   * Returns a compiler context to be used for compiling code within the test.
   */
  protected CompilerContext provideCompilerContext() {
    CompilerContext compilerContext = new CompilerContext.Builder().module(new MockModuleDef())
        .options(new PrecompileTaskOptionsImpl() {
                   @Override
                   public boolean shouldJDTInlineCompileTimeConstants() {
                     return false;
                   }
                 }
        ).build();

    compilerContext.getOptions().setSourceLevel(sourceLevel);
    compilerContext.getOptions().setStrict(true);
    compilerContext.getOptions().setGenerateJsInteropExports(true);
    return compilerContext;
  }

  /**
   * Java source level compatibility option.
   */
  protected SourceLevel sourceLevel = SourceLevel.DEFAULT_SOURCE_LEVEL;

  protected static <T> void assertContainsAll(Iterable<T> expectedMethodSnippets,
      Set<T> actualMethodSnippets) {
    List<T> missing = FluentIterable.from(expectedMethodSnippets)
        .filter(Predicates.not(Predicates.in(actualMethodSnippets)))
        .toList();
    assertTrue(missing + " not contained in " + actualMethodSnippets, missing.size() == 0);
  }

  protected void assertEqualBlock(String expected, String input)
      throws UnableToCompleteException {
    JBlock testExpression = getStatement(input);
    assertEquals(formatSource("{ " + expected + "}"),
        formatSource(testExpression.toSource()));
  }

  protected static void assertParameterTypes(JMethod method, JType... parameterTypes) {
    for (int i = 0; i < parameterTypes.length; i++) {
      JType parameterType = parameterTypes[i];
      assertEquals(parameterType, method.getParams().get(i).getType().getUnderlyingType());
    }
  }

  protected static void assertParameterTypes(
      final JProgram program, String methodName, String... parameterTypeNames) {
    JMethod method = findMethod(program, methodName);
    assertNotNull("Did not find method " + methodName, method);
    assertEquals(parameterTypeNames.length, method.getParams().size());
    JType[] parameterTypes = FluentIterable.from(Arrays.asList(parameterTypeNames))
        .transform(new Function<String, JType>() {
          @Override
          public JType apply(String typeName) {
            return findType(program, typeName);
          }
        })
        .toArray(JType.class);
    assertParameterTypes(method, parameterTypes);
  }

  protected static void assertReturnType(
      JProgram program, String methodName, String resultTypeName) {
    JMethod method = findMethod(program, methodName);
    assertNotNull("Did not find method " + methodName, method);
    JDeclaredType resultType = program.getFromTypeMap(resultTypeName);
    assertNotNull("Did not find class " + resultTypeName, resultType);
    assertEquals(resultType, method.getType().getUnderlyingType());
  }

  public Result assertTransform(String codeSnippet, JVisitor visitor)
      throws UnableToCompleteException {
    JProgram program = compileSnippet("void", codeSnippet, true);
    JMethod mainMethod = findMainMethod(program);
    visitor.accept(mainMethod);
    return new Result("void", codeSnippet, mainMethod.getBody().toSource());
  }

  protected JMethod getMethod(JProgram program, String name) {
    return findMethod(program, name);
  }

  protected JReferenceType getType(JProgram program, String name) {
    return program.getFromTypeMap(name);
  }

  protected JBlock getStatement(String statement)
      throws UnableToCompleteException {
    JProgram program = compileSnippet("void", statement, false);
    JMethod mainMethod = findMainMethod(program);
    JMethodBody body = (JMethodBody) mainMethod.getBody();
    return body.getBlock();
  }

  /**
   * Removes most whitespace while still leaving one space separating words.
   *
   * Used to make the assertEquals ignore whitespace (mostly) while still retaining meaningful
   * output when the test fails.
   */
  protected String formatSource(String source) {
    return source.replaceAll("\\s+", " ") // substitutes multiple whitespaces into one.
      .replaceAll("\\s([\\p{Punct}&&[^$]])", "$1")  // removes whitespace preceding symbols
                                                    // (except $ which can be part of an identifier)
      .replaceAll("([\\p{Punct}&&[^$]])\\s", "$1"); // removes whitespace succeeding symbols.
  }

  protected void addAll(Resource... sourceFiles) {
    for (Resource sourceFile : sourceFiles) {
      if (sourceFile != null) {
        sourceOracle.addOrReplace(sourceFile);
      }
    }
  }

  protected JExpression getExpression(String type, String expression)
      throws UnableToCompleteException {
    JProgram program = compileSnippet(type, "return " + expression + ";", false);
    JMethod mainMethod = findMainMethod(program);
    JMethodBody body = (JMethodBody) mainMethod.getBody();
    JReturnStatement returnStmt = (JReturnStatement) body.getStatements().get(0);
    return returnStmt.getExpr();
  }

  /**
   * Holds the result of a optimizations to compare with expected results.
   */
  protected final class Result {
    private final String optimized;
    private final String returnType;
    private final String userCode;

    public Result(String returnType, String userCode, String optimized) {
      this.returnType = returnType;
      this.userCode = userCode;
      this.optimized = optimized;
    }

    public void into(String expected) throws UnableToCompleteException {
      JProgram program = compileSnippet(returnType, expected, true);
      expected = getMainMethodSource(program);
      assertEquals(userCode, expected, optimized);
    }
  }
}
