/*
 * 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.dev.util.arg.SourceLevel;
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;

/**
 * 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;"
            + "  }",
        "}"
    ));

    sourceLevel = SourceLevel.DEFAULT_SOURCE_LEVEL;
  }

  public void testNestedClassDisposition() throws UnableToCompleteException {
    sourceLevel = SourceLevel.JAVA9;

    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 {
    sourceLevel = SourceLevel.JAVA9;

    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 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,
        getAdditionalTypeProviderDelegate());
    return state;
  }

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