/*
 * 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.user.rebind.rpc;

import com.google.gwt.core.ext.typeinfo.JClassType;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

/**
 * Collection of utility methods for dealing with type hierarchies.
 */
class TypeHierarchyUtils {

  /**
   * Returns <code>true</code> if the type directly implements the specified
   * interface.  The test is done on erased types; any paramaterizations
   * supplied in the arguments are ignored.
   * 
   * @param type type to check
   * @param intf interface to look for
   * @return <code>true</code> if the type directly implements the specified
   *         interface
   */
  public static boolean directlyImplementsInterface(JClassType type,
      JClassType intf) {
    type = type.getErasedType();
    intf = intf.getErasedType();
    return directlyImplementsInterfaceRecursive(new HashSet<JClassType>(),
        type, intf);
  }

  /**
   * Returns all types on the path from the root type to the serializable
   * leaves.
   * 
   * @param root the root type
   * @param leaves the set of serializable leaf types
   * @return all types on the path from the root type to the serializable leaves
   */
  public static List<JClassType> getAllTypesBetweenRootTypeAndLeaves(
      JClassType root, Collection<JClassType> leaves) {
    Map<JClassType, List<JClassType>> adjList = getInvertedTypeHierarchy(root.getErasedType());
    Set<JClassType> types = new HashSet<JClassType>();

    for (JClassType type : leaves) {
      depthFirstSearch(types, adjList, type.getErasedType());
    }

    return Arrays.asList(types.toArray(new JClassType[0]));
  }

  /**
   * Returns the immediate subtypes of the erased class argument.
   */
  public static List<JClassType> getImmediateSubtypes(JClassType clazz) {
    List<JClassType> immediateSubtypes = new ArrayList<JClassType>();
    clazz = clazz.getErasedType();
    for (JClassType subclass : clazz.getSubtypes()) {
      JClassType superclass = subclass.getSuperclass();
      if (superclass != null) {
        superclass = superclass.getErasedType();
      }

      if (superclass == clazz || clazz.isInterface() != null
          && directlyImplementsInterface(subclass, clazz)) {
        immediateSubtypes.add(subclass);
      }
    }

    return immediateSubtypes;
  }

  private static void addEdge(Map<JClassType, List<JClassType>> adjList,
      JClassType subclass, JClassType clazz) {
    List<JClassType> edges = adjList.get(subclass);
    if (edges == null) {
      edges = new ArrayList<JClassType>();
      adjList.put(subclass, edges);
    }

    edges.add(clazz);
  }

  private static void depthFirstSearch(Set<JClassType> seen,
      Map<JClassType, List<JClassType>> adjList, JClassType type) {
    if (seen.contains(type)) {
      return;
    }
    seen.add(type);

    List<JClassType> children = adjList.get(type);
    if (children != null) {
      for (JClassType child : children) {
        if (!seen.contains(child)) {
          depthFirstSearch(seen, adjList, child);
        }
      }
    }
  }

  private static boolean directlyImplementsInterfaceRecursive(
      Set<JClassType> seen, JClassType clazz, JClassType intf) {
    assert (clazz.getErasedType() == clazz);
    assert (intf.getErasedType() == intf);

    if (clazz == intf) {
      return true;
    }

    JClassType[] intfImpls = clazz.getImplementedInterfaces();

    for (JClassType intfImpl : intfImpls) {
      intfImpl = intfImpl.getErasedType();
      if (!seen.contains(intfImpl)) {
        seen.add(intfImpl);

        if (directlyImplementsInterfaceRecursive(seen, intfImpl, intf)) {
          return true;
        }
      }
    }

    return false;
  }

  /**
   * Given a root type return an adjacency list that is the inverted type
   * hierarchy.
   */
  private static Map<JClassType, List<JClassType>> getInvertedTypeHierarchy(
      JClassType root) {
    Map<JClassType, List<JClassType>> adjList = new HashMap<JClassType, List<JClassType>>();
    Set<JClassType> seen = new HashSet<JClassType>();
    Stack<JClassType> queue = new Stack<JClassType>();
    queue.push(root);
    while (!queue.isEmpty()) {
      JClassType clazz = queue.pop();
      if (seen.contains(clazz)) {
        continue;
      }
      seen.add(clazz);

      List<JClassType> immediateSubtypes = getImmediateSubtypes(clazz);
      for (JClassType immediateSubtype : immediateSubtypes) {
        // Add an edge from the immediate subtype to the supertype
        addEdge(adjList, immediateSubtype, clazz);
        queue.push(immediateSubtype);
      }
    }

    return adjList;
  }

}
