/*
 * Copyright 2010 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.dev.util.StringInterner;
import com.google.gwt.dev.util.collect.HashMap;
import com.google.gwt.dev.util.collect.Lists;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * Tracks dependencies from a {@link CompilationUnit} to {@link CompiledClass
 * CompiledClasses}.
 */
class Dependencies implements Serializable {
  /**
   * Represents a {@link Ref} that has been previously persisted.
   */
  static class Ref implements Serializable {
    private final String internalName;
    private final String hash;

    private Ref(CompiledClass cc) {
      this(cc.getInternalName(), cc.getSignatureHash()); 
    }

    private Ref(String internalName, String hash) {
      this.internalName = internalName;
      this.hash = hash;
    }

    public String getInternalName() {
      return internalName;
    }

    public String getSignatureHash() {
      return hash;
    }
  }

  Map<String, Ref> qualified = new HashMap<String, Ref>();
  Map<String, Ref> simple = new HashMap<String, Ref>();
  private final List<String> apiRefs;
  private final String myPackage;

  Dependencies() {
    this.myPackage = "";
    this.apiRefs = Lists.create();
  }

  /**
   * Initializes the set of simple and qualified dependency names, but does not
   * resolve them.
   */
  Dependencies(String myPackage, List<String> unresolvedQualified, List<String> unresolvedSimple,
      List<String> apiRefs) {
    this.myPackage =
        StringInterner.get().intern((myPackage.length() == 0) ? "" : (myPackage + '.'));
    for (String qualifiedRef : unresolvedQualified) {
      qualified.put(qualifiedRef, null);
    }
    for (String simpleRef : unresolvedSimple) {
      simple.put(simpleRef, null);
    }
    this.apiRefs = apiRefs;
  }

  /**
   * Returns the list of API references used by {@link TypeOracle} to determine type availability.
   */
  List<String> getApiRefs() {
    return apiRefs;
  }

  /**
   * Returns the list of deps that cannot be resolved at all.
   */
  List<String> findMissingApiRefs(Set<String> allValidClasses) {
    List<String> result = Lists.create();
    for (String apiRef : apiRefs) {
      if (!allValidClasses.contains(apiRef)) {
        result = Lists.add(result, apiRef);
      }
    }
    return result;
  }

  /**
   * Resolves unqualified dependencies against the global list of all valid
   * classes. Must be called before {@link #validate(String, Map, Map)}.
   */
  void resolve(Map<String, CompiledClass> allValidClasses) {
    for (Entry<String, Ref> entry : qualified.entrySet()) {
      CompiledClass cc = allValidClasses.get(entry.getKey());
      if (cc != null) {
        entry.setValue(new Ref(cc));
      }
    }

    for (Entry<String, Ref> entry : simple.entrySet()) {
      CompiledClass cc = findBySimpleName(entry.getKey(), allValidClasses);
      if (cc != null) {
        entry.setValue(new Ref(cc));
      }
    }
  }
  
  /**
   * Validate that all of my existing dependencies can be found in the global
   * set of valid classes, and resolve to structurally identical APIs.
   * 
   * @return <code>true</code> if all of my dependencies are valid
   */
  boolean validate(TreeLogger logger, Map<String, CompiledClass> allValidClasses) {
    for (Entry<String, Ref> entry : qualified.entrySet()) {
      CompiledClass theirs = allValidClasses.get(entry.getKey());
      if (!validateClass(logger, entry, theirs)) {
        return false;
      }
    }
    for (Entry<String, Ref> entry : simple.entrySet()) {
      CompiledClass theirs = findBySimpleName(entry.getKey(), allValidClasses);
      if (!validateClass(logger, entry, theirs)) {
        return false;
      }
    }
    return true;
  }

  /**
   * Tries to resolve a simple name using Java lookup rules, first checking the
   * current package, then java.lang.
   */
  private CompiledClass findBySimpleName(String ref, Map<String, CompiledClass> allValidClasses) {
    CompiledClass cc = allValidClasses.get(myPackage + ref);
    if (cc != null) {
      return cc;
    }
    return allValidClasses.get("java.lang." + ref);
  }

  /**
   * Returns true if my class is the same as their class. Uses caching to avoid
   * recomputing diffs. Updates the my entry to 'their' class if non-identical
   * objects have the same structure.
   */
  private boolean validateClass(TreeLogger logger, Entry<String, Ref> entry, CompiledClass theirs) {
    Ref mine = entry.getValue();
    boolean result;
    if ((mine == null) != (theirs == null)) {
      if (logger.isLoggable(TreeLogger.DEBUG)) {
        logger.log(TreeLogger.DEBUG, "Invalid ref: " + entry.getKey() + " mine: "
            + (mine == null ? "null" : "not null") + " theirs: "
            + (theirs == null ? "null" : "not null"));
      }
      result = false;
    } else if (mine == null && theirs == null) {
      // For package dependencies, both references being null is always the case
      result = true;
    } else if (mine.getSignatureHash().equals(theirs.getSignatureHash())) {
      result = true;
    } else {
      if (logger.isLoggable(TreeLogger.DEBUG)) {
        logger.log(TreeLogger.DEBUG, entry.getKey() + " isn't structurally same.");
      }
      result = false;
    }
    return result;
  }
}
