/*
 * 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.jjs.impl.gflow.cfg;

import com.google.gwt.dev.jjs.ast.JStatement;
import com.google.gwt.dev.jjs.impl.gflow.Assumption;
import com.google.gwt.dev.jjs.impl.gflow.SubgraphAssumptions;

import java.util.ArrayList;

/**
 * Utilities for working with Cfg.
 */
public class CfgUtil {
  public static void addGraphEdges(Cfg originalGraph, CfgNode<?> originalNode,
      CfgNode<?> newStartNode, CfgNode<?> newEndNode, Cfg newSubgraph) {
    for (int i = 0; i < originalGraph.getInEdges(originalNode).size(); ++i) {
      CfgEdge edge = new CfgEdge();
      newSubgraph.addIn(newStartNode, edge);
      newSubgraph.addGraphInEdge(edge);
    }

    for (CfgEdge e : originalGraph.getOutEdges(originalNode)) {
      CfgEdge edge = new CfgEdge(e.getRole());
      newSubgraph.addOut(newEndNode, edge);
      newSubgraph.addGraphOutEdge(edge);
    }
  }
  
  public static <A extends Assumption<?>> SubgraphAssumptions<A> 
  createGraphBottomAssumptions(Cfg graph) {
    ArrayList<A> in = new ArrayList<A>();
    for (int i = 0; i < graph.getGraphInEdges().size(); ++i) {
      in.add(null);
    }
    
    ArrayList<A> out = new ArrayList<A>();
    for (int i = 0; i < graph.getGraphOutEdges().size(); ++i) {
      out.add(null);
    }
    
    return new SubgraphAssumptions<A>(in, out);
  }

  /**
   * Create a graph with single node. Resulting graph will have same amount of 
   * input/output edges as the original node. 
   */
  public static Cfg createSingleNodeReplacementGraph(
      Cfg originalGraph,
      CfgNode<?> originalNode,
      CfgNode<?> newNode) {
    Cfg newSubgraph = new Cfg();
    newSubgraph.addNode(newNode);
    addGraphEdges(originalGraph, originalNode, newNode, newNode, newSubgraph);
    return newSubgraph;
  }
  
  /**
   * Find CFG node corresponding to the nearest statement, containing the AST
   * node of the passed node. 
   */
  public static CfgNode<?> findContainingStatement(CfgNode<?> node) {
    while (!(node.getJNode() instanceof JStatement)) {
      node = node.getParent();
    }
    
    return node;
  }

  /**
   * Find parent of containing statement.
   */
  public static CfgNode<?> findParentOfContainingStatement(CfgNode<?> node) {
    CfgNode<?> stmtNode = findContainingStatement(node);
    CfgNode<?> result = stmtNode;
    while (stmtNode.getJNode() == result.getJNode()) {
      result = result.getParent();
      if (result == null) {
        return null;
      }
      // Preconditions.checkNotNull(result, "Can't find parent for: %s", node);
    }
    
    return result;
  }
  
  private CfgUtil() {
    // 
  }
}
