/*
 * Copyright 2015 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.UnableToCompleteException;
import com.google.gwt.dev.CompilerContext;
import com.google.gwt.dev.PrecompileTaskOptionsImpl;
import com.google.gwt.dev.javac.CompilationState;
import com.google.gwt.dev.javac.CompilationStateBuilder;
import com.google.gwt.dev.javac.CompilationUnit;
import com.google.gwt.dev.javac.testing.impl.JavaResourceBase;
import com.google.gwt.dev.jjs.JavaAstConstructor;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JCastOperation;
import com.google.gwt.dev.jjs.ast.JClassLiteral;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JExpressionStatement;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodBody;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JStatement;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JVariable;
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.dev.resource.Resource;
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.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Test {@link com.google.gwt.dev.jjs.impl.GwtAstBuilder} correctly builds the AST.
 *
 * TODO(leafwang): Write tests for all other features.
 */
public class GwtAstBuilderTest extends JJSTestBase {
  Set<Resource> sources = Sets.newLinkedHashSet();

  /**
   * A Gwt AST verifier, which is used to verify that in Gwt AST, all JReferenceType instances that
   * are not in current compilation unit are external.
   */
  static class CompilationUnitJavaAstVerifier extends JVisitor {
    /**
     * Throws an assertion error if a ReferenceType that is not in current compilation unit is not
     * external.
     */
    public static void assertNonExternalOnlyInCurrentCU(CompilationUnit compilationUnit) {
      CompilationUnitJavaAstVerifier verifier =
          new CompilationUnitJavaAstVerifier(compilationUnit.getTypes());
      for (JDeclaredType type : compilationUnit.getTypes()) {
        verifier.accept(type);
      }
    }

    final List<JDeclaredType> typesInCurrentCud;

    final List<String> typeNames;

    public CompilationUnitJavaAstVerifier(List<JDeclaredType> typesInCurrentCud) {
      super();
      this.typesInCurrentCud = typesInCurrentCud;
      this.typeNames = Lists.newArrayList();
      for (JDeclaredType type : typesInCurrentCud) {
        typeNames.add(type.getName());
      }
    }

    @Override
    public void endVisit(JClassLiteral x, Context ctx) {
      /**
       * class literals only return a meaningful type after ImplementClassLiteralsAsFields has been
       * run.
       */
      if (x.getField() != null) {
        endVisit((JExpression) x, ctx);
      }
    }

    @Override
    public void endVisit(JExpression x, Context ctx) {
      if (x.getType() == null) {
        return;
      }
      assertExternal(x.getType().getUnderlyingType());
    }

    @Override
    public void endVisit(JMethod x, Context ctx) {
      assertExternal(x.getType());
    }

    @Override
    public void endVisit(JVariable x, Context ctx) {
      assertExternal(x.getType());
    }

    private void assertExternal(JType type) {
      JType typeToCheck = type;
      if (type instanceof JArrayType) {
        typeToCheck = (((JArrayType) type).getLeafType());
      }
      if (typeToCheck == null || !(typeToCheck instanceof JReferenceType)
          || typeToCheck.equals(JReferenceType.NULL_TYPE)) {
        return;
      }
      if (!typeNames.contains(typeToCheck.getName())) {
        assert (typeToCheck.isExternal());
      }
    }
  }

  @Override
  public void setUp() {
    sources.addAll(sourceOracle.getResources());
    sources.add(JavaResourceBase.createMockJavaResource("test.DalNavigationTile",
        "package test;",
        "public class DalNavigationTile extends DalTile {",
        "}"
    ));

    sources.add(JavaResourceBase.createMockJavaResource("test.DalTile",
        "package test;",
        "public class DalTile {"
            + "{ new DalRow().getTiles();"
            + "}",
        "}"
    ));

    sources.add(JavaResourceBase.createMockJavaResource("test.DalGrid",
        "package test;",
        "public class DalGrid {",
        "  public DalNavigationTile getNavigationTile() {"
            + "  DalRow row = new DalRow();"
            + "  DalNavigationTile found = null;"
            + "  for (DalTile dalTile : row.getTiles()) {"
            + "    if (dalTile instanceof DalNavigationTile) {"
            + "      found = (DalNavigationTile) dalTile;"
            + "      break;"
            + "    }"
            + "  }"
            + "  return found;"
            + "}",
        "}"
    ));

    sources.add(JavaResourceBase.createMockJavaResource("test.DalRow",
        "package test;",
        "public class DalRow {"
            + "  public DalTile[] getTiles() {"
            + "    int length = 5;"
            + "    DalTile[] result = new DalTile[length];"
            + "    for (int i = 0; i < length; i++) {"
            + "      result[i] = new DalTile();"
            + "    }"
            + "    return result;"
            + "  }",
        "}"
    ));
  }

  public void testNestedClassDisposition() throws UnableToCompleteException {
    sources.add(JavaResourceBase.createMockJavaResource("test.NestedClasses",
        "package test;",
        "public class NestedClasses {",
        "  static class StaticNestedClass {}",
        "  class InnerNestedClass {}",
        "  interface Lambda { void run(); }",
        "  public static void referencedMethod() {}",
        "  public void m() {",
        "    class LocalClass {}",
        "    Object anonymousInner = new Object(){};",
        "    Lambda lambda = () -> {};",
        "    Lambda methodRef = NestedClasses::referencedMethod;",
        "    new Lambda(){",
        "      public void run(){",
        "        Lambda lambda = () -> {};",
        "      }",
        "    };",
        "  }",
        "}"
    ));

    JProgram program = compileProgram("test.NestedClasses");
    JDeclaredType staticNested = program.getFromTypeMap("test.NestedClasses$StaticNestedClass");
    assertEquals(JDeclaredType.NestedClassDisposition.STATIC, staticNested.getClassDisposition());

    JDeclaredType innerNested = program.getFromTypeMap("test.NestedClasses$InnerNestedClass");
    assertEquals(JDeclaredType.NestedClassDisposition.INNER, innerNested.getClassDisposition());

    JDeclaredType localNested = program.getFromTypeMap("test.NestedClasses$1LocalClass");
    assertEquals(JDeclaredType.NestedClassDisposition.LOCAL, localNested.getClassDisposition());

    JDeclaredType anonymousNested = program.getFromTypeMap("test.NestedClasses$1");
    assertEquals(JDeclaredType.NestedClassDisposition.ANONYMOUS,
        anonymousNested.getClassDisposition());

    JDeclaredType lambdaNested = program.getFromTypeMap("test.NestedClasses$lambda$0$Type");
    assertEquals(JDeclaredType.NestedClassDisposition.LAMBDA, lambdaNested.getClassDisposition());

    JDeclaredType referenceNested =
        program.getFromTypeMap("test.NestedClasses$0methodref$referencedMethod$Type");
    assertEquals(JDeclaredType.NestedClassDisposition.LAMBDA,
        referenceNested.getClassDisposition());

    JDeclaredType topLevel = program.getFromTypeMap("test.NestedClasses");
    assertEquals(JDeclaredType.NestedClassDisposition.TOP_LEVEL, topLevel.getClassDisposition());

    JDeclaredType lambdaNestedInner = program.getFromTypeMap("test.NestedClasses$2$lambda$0$Type");
    assertEquals(JDeclaredType.NestedClassDisposition.LAMBDA, lambdaNestedInner
        .getClassDisposition());
  }

  public void testIntersectionBound() throws UnableToCompleteException {
    sources.add(JavaResourceBase.createMockJavaResource("test.IntersectionBound",
        "package test;",
        "public class IntersectionBound {",
        "  public void main() {",
        "    get().f();",
        "    get().g();",
        "    get().h();",
        "  }",
        "  public interface A<T> { void f(); }",
        "  public interface B { void g(); }",
        "  public interface C { void h(); }",
        "  <T extends B & A<String> & C> T get() { return null;} ",
        "}"
    ));

    JProgram program = compileProgram("test.IntersectionBound");
    JMethod mainMethod = findQualifiedMethod(program, "test.IntersectionBound.main");
    for (JStatement statement : ((JMethodBody) mainMethod.getBody()).getStatements()) {
      // TODO: should have inserted only a cast to the type needed in the specific context context,
      // but that would require some redesign. For now make sure all the casts from the intersection
      // type are emitted.
      JExpression maybeCastOperation =
          ((JMethodCall) ((JExpressionStatement) statement).getExpr()).getInstance();
      Set<String> castToTypeNames = Sets.newHashSet();
      while (maybeCastOperation instanceof  JCastOperation) {
        JCastOperation castOperation = (JCastOperation) maybeCastOperation;
        castToTypeNames.add(castOperation.getCastType().getName());
        maybeCastOperation = castOperation.getExpr();
      }

      assertEquals(
          Sets.newHashSet(Arrays.asList(
              "test.IntersectionBound$A", "test.IntersectionBound$B", "test.IntersectionBound$C")),
          castToTypeNames);
    }
  }

  public void testBridgeMethodResolution() throws UnableToCompleteException {
    sources.add(JavaResourceBase.createMockJavaResource("test.SuperInterface",
        "package test;",
        "public interface SuperInterface<T> {",
        "  void m(T t);",
        "}",
        "interface SubInterface extends  SuperInterface<String> {",
        "  void m(String t);",
        "  default SubInterface get() { ",
        "    // A lambda that will have a bridge m(Object) -> m(String)",
        "    return o -> {};",
        "  } ",
        "  static <T> void applyM(SuperInterface<T> s) { s.m(null); } ",
        "}"
    ));

    JProgram program = compileProgram("test.SuperInterface");
    JMethod applyM = findQualifiedMethod(program, "test.SubInterface.applyM");

    final Set<String> calledMethods = new HashSet<>();

    new JVisitor() {
      @Override
      public void endVisit(JMethodCall x, Context ctx) {
        calledMethods.add(x.getTarget().getQualifiedName());
      }
    }.accept(applyM);
    assertEquals(
        Sets.newHashSet(Arrays.asList("test.SuperInterface.m(Ljava/lang/Object;)V")),
        calledMethods);
  }

  public void testUniqueArrayTypeInstance() throws UnableToCompleteException {
    JProgram program = compileProgram("test.DalGrid");
    Set<String> arrayTypeNames = Sets.newHashSet();
    for (JArrayType type : program.getAllArrayTypes()) {
      arrayTypeNames.add(type.getName());
    }
    assertEquals(arrayTypeNames.size(), program.getAllArrayTypes().size());
  }

  public void testNonExternalOnlyInCurrentCud() throws UnableToCompleteException {
    CompilationState state = buildCompilationState();
    for (CompilationUnit compilationUnit : state.getCompilationUnits()) {
      CompilationUnitJavaAstVerifier.assertNonExternalOnlyInCurrentCU(compilationUnit);
    }
  }

  private CompilationState buildCompilationState() throws UnableToCompleteException {
    CompilerContext compilerContext =
        new CompilerContext.Builder().options(new PrecompileTaskOptionsImpl() {
          @Override
          public boolean shouldJDTInlineCompileTimeConstants() {
            return false;
          }
        }).build();
    compilerContext.getOptions().setSourceLevel(sourceLevel);
    compilerContext.getOptions().setStrict(true);
    CompilationState state = CompilationStateBuilder.buildFrom(logger, compilerContext, sources);
    return state;
  }

  private JProgram compileProgram(String entryType) throws UnableToCompleteException {
    CompilerContext compilerContext = provideCompilerContext();
    ;
    CompilationState state = CompilationStateBuilder.buildFrom(logger, compilerContext, sources);
    JProgram program = JavaAstConstructor.construct(logger, state, compilerContext,
        null, entryType, "com.google.gwt.lang.Exceptions");
    return program;
  }
}
