/*
 * 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.dev.javac;

import com.google.gwt.dev.javac.Dependencies.Ref;
import com.google.gwt.dev.javac.testing.impl.JavaResourceBase;
import com.google.gwt.dev.javac.testing.impl.MockJavaResource;
import com.google.gwt.dev.resource.Resource;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Test if all fileReferences in a compilationUnit are recorded correctly.
 */
public class CompilationUnitFileReferenceTest extends CompilationStateTestBase {

  public static final MockJavaResource MEMBER_INNER_SUBCLASS =
      new MockJavaResource("test.OuterSubclass") {
        @Override
        public CharSequence getContent() {
          StringBuilder code = new StringBuilder();
          code.append("package test;\n");
          code.append("public class OuterSubclass extends Outer {\n");
          code.append("  public String value() { return \"OuterSubclass\"; }\n");
          code.append("  public class MemberInnerSubclass extends MemberInner {\n");
          code.append("    public String value() { return \"MemberInnerSubclass\"; }\n");
          code.append("  }\n");
          code.append("}\n");
          return code;
        }
      };

  public static final MockJavaResource NOPACKAGE =
      new MockJavaResource("NoPackage") {
        @Override
        public CharSequence getContent() {
          StringBuilder code = new StringBuilder();
          code.append("public class NoPackage extends test.Top {\n");
          code.append("  public String value() { return \"NoPackage\"; }\n");
          code.append("}\n");
          return code;
        }
      };

  public static final MockJavaResource NOPACKAGE2 =
      new MockJavaResource("NoPackage2") {
        @Override
        public CharSequence getContent() {
          StringBuilder code = new StringBuilder();
          code.append("public class NoPackage2 extends NoPackage {\n");
          code.append("  public String value() { return \"NoPackage2\"; }\n");
          code.append("}\n");
          return code;
        }
      };

  public static final MockJavaResource OUTER =
      new MockJavaResource("test.Outer") {
        @Override
        public CharSequence getContent() {
          StringBuilder code = new StringBuilder();
          code.append("package test;\n");
          code.append("public class Outer {\n");
          code.append("  public String value() { return \"Outer\"; }\n");
          code.append("  public static class StaticInner {\n");
          code.append("    public String value() { return \"StaticInner\"; }\n");
          code.append("  }\n");
          code.append("  public class MemberInner {\n");
          code.append("    public String value() { return \"MemberInner\"; }\n");
          code.append("  }\n");
          code.append("}\n");
          return code;
        }
      };

  public static final MockJavaResource STATIC_INNER_SUBCLASS =
      new MockJavaResource("test.StaticInnerSubclass") {
        @Override
        public CharSequence getContent() {
          StringBuilder code = new StringBuilder();
          code.append("package test;\n");
          code.append("public class StaticInnerSubclass extends Outer.StaticInner {\n");
          code.append("  public String value() { return \"StaticInnerSubclass\"; }\n");
          code.append("}\n");
          return code;
        }
      };

  public static final MockJavaResource TOP = new MockJavaResource("test.Top") {
    @Override
    public CharSequence getContent() {
      StringBuilder code = new StringBuilder();
      code.append("package test;\n");
      code.append("public class Top {\n");
      code.append("  public String value() { return \"Top\"; }\n");
      code.append("}\n");
      code.append("class Top2 extends Top {\n");
      code.append("  public String value() { return \"Top2\"; }\n");
      code.append("}\n");
      return code;
    }
  };

  public static final MockJavaResource TOP3 =
      new MockJavaResource("test.Top3") {
        @Override
        public CharSequence getContent() {
          StringBuilder code = new StringBuilder();
          code.append("package test;\n");
          code.append("public class Top3 extends Top2 {\n");
          code.append("  public String value() { return \"Top3\"; }\n");
          code.append("}\n");
          return code;
        }
      };

  /**
   * This map contains the hand-computed set of references we expect each of the
   * test compilation units to have. The actual set of references computed by
   * {@link CompilationState} will be checked against this set.
   */
  private static final Map<String, Set<String>> EXPECTED_DEPENDENCIES =
      new HashMap<String, Set<String>>();

  static {
    // Setup EXPECTED_DEPENDENCIES with hand-computed data.
    initializeExpectedDependency(JavaResourceBase.FOO, JavaResourceBase.STRING.getTypeName());
    initializeExpectedDependency(JavaResourceBase.BAR, JavaResourceBase.STRING.getTypeName(),
        JavaResourceBase.FOO.getTypeName());

    initializeExpectedDependency(NOPACKAGE, JavaResourceBase.STRING.getTypeName(), TOP
        .getTypeName());
    initializeExpectedDependency(NOPACKAGE2, NOPACKAGE.getTypeName(), JavaResourceBase.STRING
        .getTypeName(), TOP.getTypeName());

    initializeExpectedDependency(TOP, JavaResourceBase.STRING.getTypeName(), "test.Top2");
    initializeExpectedDependency(TOP3, JavaResourceBase.STRING.getTypeName(), TOP.getTypeName(), "test.Top2");

    initializeExpectedDependency(OUTER, JavaResourceBase.STRING.getTypeName(), "test.Outer$MemberInner");
    initializeExpectedDependency(MEMBER_INNER_SUBCLASS, JavaResourceBase.STRING.getTypeName(),
        OUTER.getTypeName(), "test.Outer$MemberInner");

    initializeExpectedDependency(OUTER, JavaResourceBase.STRING.getTypeName());
    initializeExpectedDependency(STATIC_INNER_SUBCLASS, JavaResourceBase.STRING.getTypeName(),
        OUTER.getTypeName(), "test.Outer$StaticInner");
  }

  private static void initializeExpectedDependency(
      MockJavaResource source,
      String... typeNames) {
    Set<String> targetSet = new HashSet<String>();
    for (String typeName : typeNames) {
      targetSet.add(typeName);
    }
    EXPECTED_DEPENDENCIES.put(source.getTypeName(), targetSet);
  }

  public void testBinaryBindingsWithMemberInnerClass() {
    testBinaryBindings(OUTER, MEMBER_INNER_SUBCLASS);
  }

  public void testBinaryBindingsWithMultipleTopLevelClasses() {
    testBinaryBindings(TOP, TOP3);
  }

  public void testBinaryBindingsWithSimpleUnits() {
    testBinaryBindings(JavaResourceBase.FOO, JavaResourceBase.BAR);
  }

  public void testBinaryBindingsWithStaticInnerClass() {
    testBinaryBindings(OUTER, STATIC_INNER_SUBCLASS);
  }

  public void testBinaryNoPackage() {
    testBinaryBindings(TOP, NOPACKAGE, NOPACKAGE2);
  }

  public void testSourceBindingsWithMemberInnerClass() {
    testSourceBindings(OUTER, MEMBER_INNER_SUBCLASS);
  }

  public void testSourceBindingsWithMultipleTopLevelClasses() {
    testSourceBindings(TOP, TOP3);
  }

  public void testSourceBindingsWithSimpleUnits() {
    testSourceBindings(JavaResourceBase.FOO, JavaResourceBase.BAR);
  }

  public void testSourceBindingsWithStaticInnerClass() {
    testSourceBindings(OUTER, STATIC_INNER_SUBCLASS);
  }

  public void testSourceNoPackage() {
    testSourceBindings(TOP, NOPACKAGE, NOPACKAGE2);
  }

  public void testWithGeneratedUnits() {
    addGeneratedUnits(JavaResourceBase.FOO, JavaResourceBase.BAR);
    assertRefsMatchExpectedRefs(JavaResourceBase.FOO, JavaResourceBase.BAR);
  }

  public void testWithMixedUnits() {
    oracle.add(JavaResourceBase.FOO);
    rebuildCompilationState();
    addGeneratedUnits(JavaResourceBase.BAR);
    assertRefsMatchExpectedRefs(JavaResourceBase.FOO, JavaResourceBase.BAR);
  }

  private void assertRefsMatchExpectedRefs(MockJavaResource... files) {
    Map<String, CompilationUnit> unitMap = state.getCompilationUnitMap();
    for (MockJavaResource file : files) {
      String typeName = file.getTypeName();
      Dependencies dependencies = unitMap.get(typeName).getDependencies();
      Set<String> actualTypeNames = new HashSet<String>();
      for (Ref ref : dependencies.qualified.values()) {
        if (ref != null) {
          actualTypeNames.add(ref.getInternalName().replace('/', '.'));
        }
      }
      for (Ref ref : dependencies.simple.values()) {
        if (ref != null) {
          actualTypeNames.add(ref.getInternalName().replace('/', '.'));
        }
      }
      actualTypeNames.remove(null);
      // Not tracking deps on Object.
      actualTypeNames.remove("java.lang.Object");
      // Don't care about self dep.
      actualTypeNames.remove(typeName);
      Set<String> expectedTypeNames = EXPECTED_DEPENDENCIES.get(typeName);
      assertEquals("Resource: " + file, expectedTypeNames, actualTypeNames);
    }
  }

  /**
   * Independently compiles each file in order to force each subsequent unit to
   * have only binary references to the previous unit(s). This tests the binary
   * reference matching in {@link CompilationState}.
   */
  private void testBinaryBindings(MockJavaResource... files) {
    for (Resource sourceFile : files) {
      oracle.add(sourceFile);
      rebuildCompilationState();
    }
    assertRefsMatchExpectedRefs(files);
  }

  /**
   * Compiles all files together so that all units will have source references
   * to each other. This tests the source reference matching in
   * {@link CompilationState}.
   */
  private void testSourceBindings(MockJavaResource... files) {
    for (Resource sourceFile : files) {
      oracle.add(sourceFile);
    }
    rebuildCompilationState();
    assertRefsMatchExpectedRefs(files);
  }
}
