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

import com.google.gwt.dev.jjs.impl.gflow.TransformationFunction.Transformation;
import com.google.gwt.thirdparty.guava.common.base.Preconditions;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;

/**
 * A solver to solve all kinds of analyses defined in the package.
 * Uses iterative worklist algorithm. 
 * 
 * Solver might be forward or backwards working. Both directions will always 
 * produce a valid fixed point, which depends on direction. As a rule, 
 * forward analysis benefits from forward direction, backwards - from the 
 * opposite.
 *
 * @param <N> graph node type.
 * @param <E> graph edge type.
 * @param <T> graph transformer type.
 * @param <G> graph type.
 * @param <A> assumption type.
 */
public class AnalysisSolver<N, E, T, G extends Graph<N, E, T>, 
                            A extends Assumption<A>> {
  /**
   * Adapter from IntegratedFlowFunction to FlowFunction. If integrated function
   * decides to perform transformation, replacement graph is recursively 
   * analyzed and result return without actually performing transformation,  
   */
  private final class IntegratedFlowFunctionAdapter
      implements FlowFunction<N, E, G, A> {
    private IntegratedFlowFunction<N, E, T, G, A> flowFunction;

    private IntegratedFlowFunctionAdapter(
        IntegratedAnalysis<N, E, T, G, A> analysis) {
      flowFunction = analysis.getIntegratedFlowFunction();
    }

    public void interpret(final N node, G graph, 
        final AssumptionMap<E, A> assumptionMap) {
      final boolean[] mapWasModified = new boolean[1];
      Transformation<T, G> transformation = flowFunction.interpretOrReplace(
          node, graph, new AssumptionMap<E, A>() {
            public A getAssumption(E edge) {
              return assumptionMap.getAssumption(edge);
            }

            public void setAssumption(E edge, A assumption) {
              mapWasModified[0] = true;
              assumptionMap.setAssumption(edge, assumption);
            }
          });

      if (transformation == null) {
        return;
      }
      
      Preconditions.checkArgument(!mapWasModified[0]);
      
      final G newSubgraph = transformation.getNewSubgraph();

      if (debug) {
        System.err.println("Applying transformation: " + transformation);
        System.err.println("Replacing");
        System.err.println(node);
        System.err.println("With graph:");
        System.err.println(newSubgraph);
      }

      final List<E> inEdges = graph.getInEdges(node);
      final List<E> outEdges = graph.getOutEdges(node);

      Preconditions.checkArgument(newSubgraph.getGraphInEdges().size() == 
        inEdges.size());

      Preconditions.checkArgument(newSubgraph.getGraphOutEdges().size() == 
        outEdges.size());

      iterate(newSubgraph,
          new IntegratedAnalysis<N, E, T, G, A>() {
            public IntegratedFlowFunction<N, E, T, G, A> 
            getIntegratedFlowFunction() {
              return flowFunction;
            }

            public void setInitialGraphAssumptions(G graph,
                AssumptionMap<E, A> newAssumptionMap) {
              for (int i = 0; i < inEdges.size(); ++i) {
                newAssumptionMap.setAssumption(newSubgraph.getGraphInEdges().get(i),
                    assumptionMap.getAssumption(inEdges.get(i))); 
              }
              
              for (int i = 0; i < outEdges.size(); ++i) {
                newAssumptionMap.setAssumption(newSubgraph.getGraphOutEdges().get(i),
                    assumptionMap.getAssumption(outEdges.get(i))); 
              }
            }

          });

      for (int i = 0; i < inEdges.size(); ++i) {
        assumptionMap.setAssumption(inEdges.get(i), 
            getEdgeAssumption(newSubgraph, newSubgraph.getGraphInEdges().get(i)));
      }
      
      for (int i = 0; i < outEdges.size(); ++i) {
        assumptionMap.setAssumption(outEdges.get(i), 
            getEdgeAssumption(newSubgraph, newSubgraph.getGraphOutEdges().get(i)));
      }
    }
  }
  
  public static boolean debug = false;

  /**
   * Solve a non-integrated analysis.
   * 
   * @param <N> graph node type.
   * @param <E> graph edge type.
   * @param <T> graph transformer type.
   * @param <G> graph type.
   * @param <A> assumption type.
   */
  public static <N, E, T, G extends Graph<N, E, T>, A extends Assumption<A>> 
  Map<E, A> solve(G g, Analysis<N, E, G, A> analysis, boolean forward) {
    return new AnalysisSolver<N, E, T, G, A>(forward).solve(g, analysis);
  }

  /**
   * Solve a integrated analysis.
   * 
   * @param <N> graph node type.
   * @param <E> graph edge type.
   * @param <T> graph transformer type.
   * @param <G> graph type.
   * @param <A> assumption type.
   */
  public static <N, E, T, G extends Graph<N, E, T>, A extends Assumption<A>> 
  boolean solveIntegrated(G g, IntegratedAnalysis<N, E, T, G, A> analysis, 
      boolean forward) {
    return new AnalysisSolver<N, E, T, G, A>(forward).solveIntegrated(g, 
        analysis);
  }
  
  /**
   * If <code>true</code>, then we are moving forward. Moving backwards 
   * otherwise.
   */
  private final boolean forward;

  /**
   * @param forward <code>true</code> if solvers moves forward.
   */
  private AnalysisSolver(boolean forward) {
    this.forward = forward;
  }
  
  /**
   * Apply all transformations based on a found fixed point.
   */
  private boolean actualize(G graph, 
      final IntegratedAnalysis<N, E, T, G, A> analysis) {
    TransformationFunction<N, E, T, G, A> function = 
      new TransformationFunction<N, E, T, G, A>() {
      public Transformation<T, G> transform(final N node, final G graph,
          AssumptionMap<E, A> assumptionMap) {
        final boolean[] didAssumptionChange = new boolean[1];
        Transformation<T, G> transformation = analysis.getIntegratedFlowFunction().interpretOrReplace(
              node, graph, new AssumptionMap<E, A>() {
                public A getAssumption(E edge) {
                  Preconditions.checkArgument(graph.getStart(edge) == node
                      || graph.getEnd(edge) == node);
                  return getEdgeAssumption(graph, edge);
                }

                public void setAssumption(E edge, A assumption) {
                  Preconditions.checkArgument(graph.getStart(edge) == node
                      || graph.getEnd(edge) == node);
                 didAssumptionChange[0] = true;
                }
              });
        Preconditions.checkArgument(transformation == null ||
            !didAssumptionChange[0]);
        return transformation;
      }
    };
    return applyTransformation(graph, function);
  }

  private boolean applyTransformation(final G graph, 
      TransformationFunction<N, E, T, G, A> transformationFunction) {
    boolean didChange = false;

    for (final N node : graph.getNodes()) {
      Transformation<T, G> transformation = transformationFunction.transform(
          node, graph, new AssumptionMap<E, A>() {
            public A getAssumption(E edge) {
              Preconditions.checkArgument(graph.getStart(edge) == node
                  || graph.getEnd(edge) == node);
              return getEdgeAssumption(graph, edge);
            }

            public void setAssumption(E edge, A assumption) {
              throw new IllegalStateException(
                  "Transformations should not change assumptions");
            }
          });
      if (transformation != null) {
        T actualizer = transformation.getGraphTransformer();
        Preconditions.checkNotNull(actualizer, "Null actualizer from: %s",
            transformationFunction);
        didChange = graph.transform(node, actualizer) || didChange;
      }
    }

    return didChange;
  }

  private LinkedHashSet<N> buildInitialWorklist(G g) {
    ArrayList<N> nodes = new ArrayList<N>(g.getNodes());
    LinkedHashSet<N> worklist = new LinkedHashSet<N>(nodes.size());
    if (!forward) {
      Collections.reverse(nodes);
    } 
    worklist.addAll(nodes);
    return worklist;
  }

  @SuppressWarnings("unchecked")
  private A getEdgeAssumption(G graph, E edge) {
    return (A) graph.getEdgeData(edge);
  }

  private void initGraphAssumptions(Analysis<N, E, G, A> analysis, final G graph) {
    analysis.setInitialGraphAssumptions(graph, new AssumptionMap<E, A>() {
      public A getAssumption(E edge) {
        return getEdgeAssumption(graph, edge);
      }

      public void setAssumption(E edge, A assumption) {
        setEdgeAssumption(graph, edge, assumption);
      }
    });
  }
  
  /**
   * Find a fixed point of integrated analysis by wrapping it with 
   * IntegratedFlowFunctionAdapter and calling
   * {@link #solveImpl(Graph, Analysis)}. 
   */
  private void iterate(G graph,
      final IntegratedAnalysis<N, E, T, G, A> integratedAnalysis) {
    if (debug) {
      System.err.println("-----------------------------------------");
      System.err.println("Iterate started on:");
      System.err.println(graph);
      System.err.println("-----------------------------------------");
    }
    final IntegratedFlowFunctionAdapter adapter = 
      new IntegratedFlowFunctionAdapter(integratedAnalysis);

    Analysis<N, E, G, A> analysis = new Analysis<N, E, G, A>() {
      public FlowFunction<N, E, G, A> getFlowFunction() {
        return adapter;
      }

      public void setInitialGraphAssumptions(G graph,
          AssumptionMap<E, A> assumptionMap) {
        integratedAnalysis.setInitialGraphAssumptions(graph, assumptionMap);
      }
    };
    
    solveImpl(graph, analysis);
  }

  private void resetEdgeData(G graph) {
    for (N node : graph.getNodes()) {
      for (E e : graph.getInEdges(node)) {
        graph.setEdgeData(e, null);
      }
      for (E e : graph.getOutEdges(node)) {
        graph.setEdgeData(e, null);
      }
    }
    for (E e : graph.getGraphOutEdges()) {
      graph.setEdgeData(e, null);
    }
    for (E e : graph.getGraphInEdges()) {
      graph.setEdgeData(e, null);
    }
  }

  private void setEdgeAssumption(G graph, E edge, A assumption) {
    graph.setEdgeData(edge, assumption);
  }

  /**
   * Solve a non-integrated analysis.
   */
  private Map<E, A> solve(G g, Analysis<N, E, G, A> analysis) {
    solveImpl(g, analysis);

    Map<E, A> result = new HashMap<E, A>();
    
    for (N n : g.getNodes()) {
      for (E e : g.getInEdges(n)) {
        result.put(e, getEdgeAssumption(g, e));
      }
      for (E e : g.getOutEdges(n)) {
        result.put(e, getEdgeAssumption(g, e));
      }
    }
    for (E e : g.getGraphInEdges()) {
      result.put(e, getEdgeAssumption(g, e));
    }
    for (E e : g.getGraphOutEdges()) {
      result.put(e, getEdgeAssumption(g, e));
    }

    return result;
  }

  /**
   * Solve a non-integrated analysis.
   */
  private void solveImpl(final G graph, Analysis<N, E, G, A> analysis) {
    FlowFunction<N, E, G, A> flowFunction = analysis.getFlowFunction();

    final LinkedHashSet<N> worklist = buildInitialWorklist(graph);
    resetEdgeData(graph);
    initGraphAssumptions(analysis, graph);

    while (!worklist.isEmpty()) {
      Iterator<N> iterator = worklist.iterator();
      final N node = iterator.next();
      iterator.remove();

      flowFunction.interpret(node, graph, new AssumptionMap<E, A>() {
        public A getAssumption(E edge) {
          Preconditions.checkArgument(graph.getStart(edge) == node
              || graph.getEnd(edge) == node);
          return getEdgeAssumption(graph, edge);
        }

        public void setAssumption(E edge, A assumption) {
          N start = graph.getStart(edge);
          N end = graph.getEnd(edge);
          Preconditions.checkArgument(start == node || end == node);

          if (!AssumptionUtil.equals(getEdgeAssumption(graph, edge), assumption)) {
            setEdgeAssumption(graph, edge, assumption);

            if (start == node) {
              if (end != null) {
                worklist.add(end);
              }
            } else if (end == node) {
              if (start != null) {
                worklist.add(start);
              }
            } else {
              throw new IllegalStateException();
            }
          }
        }
      });
    }
  }

  /**
   * Solve an integrated analysis.
   * 
   * Finds a fixed point by using an IntegratedFlowFunctionAdapter and 
   * recursing into {@link #solve(Graph, Analysis)}. Applies analysis 
   * transformations based on the found fixed point.
   */
  private boolean solveIntegrated(G g, IntegratedAnalysis<N, E, T, G, A> analysis) {
    iterate(g, analysis);
    return actualize(g, analysis);
  }
}
