/*
 * Copyright 2008 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.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.CompilerContext;
import com.google.gwt.dev.javac.CompilationStateBuilder.CompileMoreLater;
import com.google.gwt.dev.javac.typemodel.TypeOracle;
import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
import com.google.gwt.thirdparty.guava.common.annotations.VisibleForTesting;
import com.google.gwt.thirdparty.guava.common.base.Function;
import com.google.gwt.thirdparty.guava.common.base.Predicates;
import com.google.gwt.thirdparty.guava.common.collect.FluentIterable;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * Encapsulates the state of active compilation units in a particular module.
 * State is accumulated throughout the life cycle of the containing module and
 * may be invalidated at certain times and recomputed.
 */
public class CompilationState {

  /**
   * Classes mapped by internal name.
   */
  protected final Map<String, CompiledClass> classFileMap = new HashMap<String, CompiledClass>();

  /**
   * Classes mapped by source name.
   */
  protected final Map<String, CompiledClass> classFileMapBySource =
      new HashMap<String, CompiledClass>();

  /**
   * All my compilation units.
   */
  protected final Map<String, CompilationUnit> unitMap = new HashMap<String, CompilationUnit>();

  private int cachedGeneratedSourceCount = 0;

  private int cachedStaticSourceCount = 0;

  private final CompileMoreLater compileMoreLater;

  private CompilerContext compilerContext;

  /**
   * Unmodifiable view of {@link #classFileMap}.
   */
  private final Map<String, CompiledClass> exposedClassFileMap =
      Collections.unmodifiableMap(classFileMap);

  /**
   * Unmodifiable view of {@link #classFileMapBySource}.
   */
  private final Map<String, CompiledClass> exposedClassFileMapBySource =
      Collections.unmodifiableMap(classFileMapBySource);

  /**
   * Unmodifiable view of {@link #unitMap}.
   */
  private final Map<String, CompilationUnit> exposedUnitMap = Collections.unmodifiableMap(unitMap);

  /**
   * Unmodifiable view of all units.
   */
  private final Collection<CompilationUnit> exposedUnits =
      Collections.unmodifiableCollection(unitMap.values());

  private int generatedSourceCount = 0;

  private int staticSourceCount = 0;

  /**
   * Our type oracle.
   */
  private final TypeOracle typeOracle;

  /**
   * Updates our type oracle.
   */
  private final CompilationUnitTypeOracleUpdater typeOracleUpdater;

  CompilationState(TreeLogger logger, CompilerContext compilerContext,
      TypeOracle typeOracle, CompilationUnitTypeOracleUpdater typeOracleUpdater,
      Collection<CompilationUnit> units, CompileMoreLater compileMoreLater) {
    this.compileMoreLater = compileMoreLater;
    this.compilerContext = compilerContext;
    this.typeOracle = typeOracle;
    this.typeOracleUpdater = typeOracleUpdater;
    assimilateUnits(logger, units);
  }

  /**
   * Compiles the given source files (unless cached) and adds them to the
   * CompilationState.
   * If the compiler aborts, logs the error and throws UnableToCompleteException.
   */
  public void addGeneratedCompilationUnits(TreeLogger logger,
      Collection<GeneratedUnit> generatedUnits) throws UnableToCompleteException {
    Event generatedUnitsAddEvent = SpeedTracerLogger.start(
        DevModeEventType.COMP_STATE_ADD_GENERATED_UNITS);
    try {
      logger = logger.branch(TreeLogger.DEBUG, "Adding '"
          + generatedUnits.size() + "' new generated units");
      generatedUnitsAddEvent.addData("# new generated units", "" + generatedUnits.size());
      Collection<CompilationUnit> newUnits = compileMoreLater.addGeneratedTypes(
          logger, generatedUnits, this);
      assimilateUnits(logger, newUnits);
    } finally {
      generatedUnitsAddEvent.end();
    }
  }

  public int getCachedGeneratedSourceCount() {
    return cachedGeneratedSourceCount;
  }

  public int getCachedStaticSourceCount() {
    return cachedStaticSourceCount;
  }

  /**
   * Returns a map of all compiled classes by internal name.
   */
  public Map<String, CompiledClass> getClassFileMap() {
    return exposedClassFileMap;
  }

  /**
   * Returns a map of all compiled classes by source name.
   */
  public Map<String, CompiledClass> getClassFileMapBySource() {
    return exposedClassFileMapBySource;
  }

  /**
   * Returns an unmodifiable view of the set of compilation units, mapped by the
   * main type's qualified source name.
   */
  public Map<String, CompilationUnit> getCompilationUnitMap() {
    return exposedUnitMap;
  }

  /**
   * Returns an unmodifiable view of the set of compilation units.
   */
  public Collection<CompilationUnit> getCompilationUnits() {
    return exposedUnits;
  }

  public Iterable<String> getQualifiedJsInteropRootTypesNames() {
    Function<CompilationUnit, String> toRootTypeName = new Function<CompilationUnit, String>() {
      @Override
      public String apply(CompilationUnit compilationUnit) {
        return compilationUnit.hasJsInteropRootType() ? compilationUnit.getTypeName() : null;
      }
    };
    return FluentIterable.from(unitMap.values())
        .transform(toRootTypeName)
        .filter(Predicates.notNull());
  }

  public CompilerContext getCompilerContext() {
    return compilerContext;
  }

  public int getGeneratedSourceCount() {
    return generatedSourceCount;
  }

  public int getStaticSourceCount() {
    return staticSourceCount;
  }

  public TypeOracle getTypeOracle() {
    return typeOracle;
  }

  @VisibleForTesting
  public Map<String, CompiledClass> getValidClasses() {
    return compileMoreLater.getValidClasses();
  }

  /**
   * Whether any errors were encountered while building this compilation state.
   */
  public boolean hasErrors() {
    for (CompilationUnit unit : unitMap.values()) {
      if (unit.isError()) {
        return true;
      }
    }
    return false;
  }

  public void incrementCachedGeneratedSourceCount(int extraCachedGeneratedSourceCount) {
    cachedGeneratedSourceCount += extraCachedGeneratedSourceCount;
  }

  public void incrementCachedStaticSourceCount(int extraCachedStaticSourceCount) {
    cachedStaticSourceCount += extraCachedStaticSourceCount;
  }

  public void incrementGeneratedSourceCount(int extraGeneratedSourceCount) {
    generatedSourceCount += extraGeneratedSourceCount;
  }

  public void incrementStaticSourceCount(int extraStaticSourceCount) {
    staticSourceCount += extraStaticSourceCount;
  }

  /**
   * For testing.
   */
  CompilationUnitTypeOracleUpdater getTypeOracleUpdater() {
    return typeOracleUpdater;
  }

  private void assimilateUnits(TreeLogger logger, Collection<CompilationUnit> units) {
    for (CompilationUnit unit : units) {
      unitMap.put(unit.getTypeName(), unit);
      for (CompiledClass compiledClass : unit.getCompiledClasses()) {
        classFileMap.put(compiledClass.getInternalName(), compiledClass);
        classFileMapBySource.put(compiledClass.getSourceName(), compiledClass);
      }
    }

    CompilationUnitInvalidator.retainValidUnits(logger, units, compileMoreLater.getValidClasses(),
        compilerContext.getCompilationErrorsIndex());
    typeOracleUpdater.addNewUnits(logger, units);
  }
}
