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

import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.dev.cfg.Rule;
import com.google.gwt.dev.cfg.Rules;
import com.google.gwt.dev.javac.StandardGeneratorContext;
import com.google.gwt.dev.javac.rebind.CachedRebindResult;
import com.google.gwt.dev.javac.rebind.RebindCache;
import com.google.gwt.dev.javac.rebind.RebindResult;
import com.google.gwt.dev.javac.rebind.RebindRuleResolver;
import com.google.gwt.dev.javac.rebind.RebindStatus;
import com.google.gwt.dev.jdt.RebindOracle;
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 java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Implements rebind logic in terms of a variety of other well-known oracles.
 */
public class StandardRebindOracle implements RebindOracle {

  /**
   * Makes the actual deferred binding decision by examining rules.
   */
  private final class Rebinder implements RebindRuleResolver {

    @Override
    public boolean checkRebindRuleResolvable(String typeName) {
      try {
        if (getRebindRule(TreeLogger.NULL, typeName) != null) {
          return true;
        }
      } catch (UnableToCompleteException utcEx) {
      }
      return false;
    }

    public String rebind(TreeLogger logger, String typeName, ArtifactAcceptor artifactAcceptor)
        throws UnableToCompleteException {
      Event rebindEvent = SpeedTracerLogger.start(DevModeEventType.REBIND, "Type Name", typeName);
      try {
        genCtx.setPropertyOracle(propOracle);
        genCtx.setRebindRuleResolver(this);
        Rule rule = getRebindRule(logger, typeName);

        if (rule == null) {
          return typeName;
        }

        CachedRebindResult cachedResult = rebindCacheGet(rule, typeName);
        if (cachedResult != null) {
          genCtx.setCachedGeneratorResult(cachedResult);
        }

        // realize the rule (call a generator, or do type replacement, etc.)
        RebindResult result = rule.realize(logger, genCtx, typeName);

        // handle rebind result caching (if enabled)
        String resultTypeName =
            processCacheableResult(logger, rule, typeName, cachedResult, result);

        /*
         * Finalize new artifacts from the generator context
         */
        if (artifactAcceptor != null) {
          // Go ahead and call finish() to accept new artifacts.
          ArtifactSet newlyGeneratedArtifacts = genCtx.finish(logger);
          if (!newlyGeneratedArtifacts.isEmpty()) {
            artifactAcceptor.accept(logger, newlyGeneratedArtifacts);
          }
        }

        assert (resultTypeName != null);
        return resultTypeName;
      } finally {
        rebindEvent.end();
      }
    }

    private Rule getRebindRule(TreeLogger logger, String typeName) throws UnableToCompleteException {

      // Make the rebind decision.
      //
      if (rules.isEmpty()) {
        logger.log(TreeLogger.DEBUG, "No rules are defined, so no substitution can occur", null);
        return null;
      }

      Rule minCostRuleSoFar = null;

      for (Iterator<Rule> iter = rules.iterator(); iter.hasNext();) {
        Rule rule = iter.next();

        // Branch the logger.
        //
        TreeLogger branch = Messages.TRACE_CHECKING_RULE.branch(logger, rule, null);

        if (rule.isApplicable(branch, genCtx, typeName)) {
          Messages.TRACE_RULE_MATCHED.log(logger, null);
          return rule;
        } else {
          Messages.TRACE_RULE_DID_NOT_MATCH.log(logger, null);

          // keep track of fallback partial matches
          if (minCostRuleSoFar == null) {
            minCostRuleSoFar = rule;
          }
          assert rule.getFallbackEvaluationCost() != 0;
          // if we found a better match, keep that as the best candidate so far
          if (rule.getFallbackEvaluationCost() <= minCostRuleSoFar.getFallbackEvaluationCost()) {
            if (logger.isLoggable(TreeLogger.DEBUG)) {
              logger.log(TreeLogger.DEBUG, "Found better fallback match for " + rule);
            }
            minCostRuleSoFar = rule;
          }
        }
      }

      // if we reach this point, it means we did not find an exact match
      // and we may have a partial match based on fall back values
      assert minCostRuleSoFar != null;
      if (minCostRuleSoFar.getFallbackEvaluationCost() < Integer.MAX_VALUE) {
        if (logger.isLoggable(TreeLogger.INFO)) {
          logger.log(TreeLogger.INFO, "Could not find an exact match rule. Using 'closest' rule "
              + minCostRuleSoFar
              + " based on fall back values. You may need to implement a specific "
              + "binding in case the fall back behavior does not replace the missing binding");
        }
        if (logger.isLoggable(TreeLogger.DEBUG)) {
          logger.log(TreeLogger.DEBUG, "No exact match was found, using closest match rule "
              + minCostRuleSoFar);
        }
        return minCostRuleSoFar;
      }

      // No matching rule for this type.
      return null;
    }

    /*
     * Decide how to handle integrating a previously cached result, and whether
     * to cache the new result for the future.
     */
    private String processCacheableResult(TreeLogger logger, Rule rule, String typeName,
        CachedRebindResult cachedResult, RebindResult newResult) {

      String resultTypeName = newResult.getReturnedTypeName();

      if (!genCtx.isGeneratorResultCachingEnabled()) {
        return resultTypeName;
      }

      RebindStatus status = newResult.getResultStatus();
      switch (status) {

        case USE_EXISTING:
          // in this case, no newly generated or cached types are needed
          break;

        case USE_ALL_NEW_WITH_NO_CACHING:
          /*
           * in this case, new artifacts have been generated, but no need to
           * cache results (as the generator is probably not able to take
           * advantage of caching).
           */
          break;

        case USE_ALL_NEW:
          // use all new results, add a new cache entry
          cachedResult =
              new CachedRebindResult(newResult.getReturnedTypeName(), genCtx.getArtifacts(), genCtx
                  .getGeneratedUnitMap(), System.currentTimeMillis(), newResult.getClientDataMap());
          rebindCachePut(rule, typeName, cachedResult);
          break;

        case USE_ALL_CACHED:
          // use all cached results
          assert (cachedResult != null);

          genCtx.commitArtifactsFromCache(logger);
          genCtx.addGeneratedUnitsFromCache();

          // use cached type name
          resultTypeName = cachedResult.getReturnedTypeName();
          break;

        case USE_PARTIAL_CACHED:
          /*
           * Add cached generated units marked for reuse to the context.
           * TODO(jbrosenberg): add support for reusing artifacts as well as
           * GeneratedUnits.
           */
          genCtx.addGeneratedUnitsMarkedForReuseFromCache();

          /*
           * Create a new cache entry using the composite set of new and reused
           * cached results currently in genCtx.
           */
          cachedResult =
              new CachedRebindResult(newResult.getReturnedTypeName(), genCtx.getArtifacts(), genCtx
                  .getGeneratedUnitMap(), System.currentTimeMillis(), newResult.getClientDataMap());
          rebindCachePut(rule, typeName, cachedResult);
          break;
      }
      return resultTypeName;
    }
  }

  private final Map<String, String> typeNameBindingMap = new HashMap<String, String>();

  private final StandardGeneratorContext genCtx;

  private final PropertyOracle propOracle;

  private RebindCache rebindCache = null;

  private final Rules rules;

  public StandardRebindOracle(PropertyOracle propOracle, Rules rules,
      StandardGeneratorContext genCtx) {
    this.propOracle = propOracle;
    this.rules = rules;
    this.genCtx = genCtx;
  }

  /**
   * Invalidates the given source type name, so the next rebind request will
   * generate the type again.
   */
  public void invalidateRebind(String sourceTypeName) {
    typeNameBindingMap.remove(sourceTypeName);
  }

  public String rebind(TreeLogger logger, String typeName) throws UnableToCompleteException {
    return rebind(logger, typeName, null);
  }

  public String rebind(TreeLogger logger, String typeName, ArtifactAcceptor artifactAcceptor)
      throws UnableToCompleteException {

    String resultTypeName = typeNameBindingMap.get(typeName);
    if (resultTypeName == null) {
      logger = Messages.TRACE_TOPLEVEL_REBIND.branch(logger, typeName, null);

      Rebinder rebinder = new Rebinder();
      resultTypeName = rebinder.rebind(logger, typeName, artifactAcceptor);
      typeNameBindingMap.put(typeName, resultTypeName);

      Messages.TRACE_TOPLEVEL_REBIND_RESULT.log(logger, resultTypeName, null);
    }
    return resultTypeName;
  }

  public void setRebindCache(RebindCache cache) {
    this.rebindCache = cache;
  }

  private CachedRebindResult rebindCacheGet(Rule rule, String typeName) {
    if (rebindCache != null) {
      return rebindCache.get(rule, typeName);
    }
    return null;
  }

  private void rebindCachePut(Rule rule, String typeName, CachedRebindResult result) {
    if (rebindCache != null) {
      rebindCache.put(rule, typeName, result);
    }
  }
}
