// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking;

import com.android.tools.r8.experimental.graphinfo.ClassGraphNode;
import com.android.tools.r8.experimental.graphinfo.FieldGraphNode;
import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
import com.android.tools.r8.experimental.graphinfo.GraphEdgeInfo;
import com.android.tools.r8.experimental.graphinfo.GraphEdgeInfo.EdgeKind;
import com.android.tools.r8.experimental.graphinfo.GraphNode;
import com.android.tools.r8.experimental.graphinfo.KeepRuleGraphNode;
import com.android.tools.r8.experimental.graphinfo.MethodGraphNode;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.position.TextPosition;
import com.android.tools.r8.position.TextRange;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.FieldReference;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.TypeReference;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.StringUtils.BraceType;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Deque;
import java.util.IdentityHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * Implementation of the whyareyoukeeping rule using an R8 kept-graph consumer.
 *
 * <p>This class is not intended for public use and clients should define their own consumer
 * instead.
 */
public class WhyAreYouKeepingConsumer extends CollectingGraphConsumer {

  // Single-linked path description when BF searching for a path.
  private static class GraphPath {
    final GraphNode node;
    final GraphPath path;

    public GraphPath(GraphNode node, GraphPath path) {
      assert node != null;
      this.node = node;
      this.path = path;
    }
  }

  public WhyAreYouKeepingConsumer(GraphConsumer subConsumer) {
    super(subConsumer);
  }

  public ClassGraphNode getClassNode(ClassReference clazz) {
    for (GraphNode node : getTargets()) {
      if (node instanceof ClassGraphNode && ((ClassGraphNode) node).getReference() == clazz) {
        return (ClassGraphNode) node;
      }
    }
    return null;
  }

  public MethodGraphNode getMethodNode(MethodReference method) {
    for (GraphNode node : getTargets()) {
      if (node instanceof MethodGraphNode && ((MethodGraphNode) node).getReference() == method) {
        return (MethodGraphNode) node;
      }
    }
    return null;
  }

  public FieldGraphNode getFieldNode(FieldReference field) {
    for (GraphNode node : getTargets()) {
      if (node instanceof FieldGraphNode && ((FieldGraphNode) node).getReference() == field) {
        return (FieldGraphNode) node;
      }
    }
    return null;
  }

  public void printWhyAreYouKeeping(ClassReference reference, PrintStream out) {
    ClassGraphNode node = getClassNode(reference);
    printWhyAreYouKeeping(node != null ? node : new ClassGraphNode(false, reference), out);
  }

  public void printWhyAreYouKeeping(MethodReference reference, PrintStream out) {
    MethodGraphNode node = getMethodNode(reference);
    printWhyAreYouKeeping(node != null ? node : new MethodGraphNode(false, reference), out);
  }

  public void printWhyAreYouKeeping(FieldReference reference, PrintStream out) {
    FieldGraphNode node = getFieldNode(reference);
    printWhyAreYouKeeping(node != null ? node : new FieldGraphNode(false, reference), out);
  }

  public void printWhyAreYouKeeping(GraphNode node, PrintStream out) {
    Formatter formatter = new Formatter(out);
    List<Pair<GraphNode, GraphEdgeInfo>> path = findShortestPathTo(node);
    if (path == null) {
      printNothingKeeping(node, out);
      return;
    }
    formatter.startItem(getNodeString(node));
    for (int i = path.size() - 1; i >= 0; i--) {
      Pair<GraphNode, GraphEdgeInfo> edge = path.get(i);
      printEdge(edge.getFirst(), edge.getSecond(), formatter);
    }
    formatter.endItem();
  }

  private void printNothingKeeping(GraphNode node, PrintStream out) {
    out.print("Nothing is keeping ");
    out.println(getNodeString(node));
  }

  private void printNothingKeeping(ClassReference clazz, PrintStream out) {
    out.print("Nothing is keeping ");
    out.println(DescriptorUtils.descriptorToJavaType(clazz.getDescriptor()));
  }

  private List<Pair<GraphNode, GraphEdgeInfo>> findShortestPathTo(final GraphNode node) {
    if (node == null) {
      return null;
    }
    Map<GraphNode, GraphNode> seen = new IdentityHashMap<>();
    Deque<GraphPath> queue = new LinkedList<>();
    GraphPath path = null;
    GraphNode current = node;
    while (true) {
      Map<GraphNode, Set<GraphEdgeInfo>> sources = getSourcesTargeting(current);
      if (sources == null) {
        // We have reached a root or the current node is not targeted at all.
        return getCanonicalPath(path, node);
      }
      assert !sources.isEmpty();
      for (GraphNode source : sources.keySet()) {
        if (!seen.containsKey(source)) {
          seen.put(source, source);
          queue.addLast(new GraphPath(source, path));
        }
      }
      // The source set was not empty, thus we don't have a real root, but all sources are seen!
      if (queue.isEmpty()) {
        return getCanonicalPath(new GraphPath(GraphNode.cycle(), path), node);
      }
      path = queue.removeFirst();
      current = path.node;
    }
  }

  // Convert a internal path representation to the external API and compute the edge reasons.
  private List<Pair<GraphNode, GraphEdgeInfo>> getCanonicalPath(
      GraphPath path, GraphNode endTarget) {
    if (path == null) {
      // If there is no path to endTarget, treat it as not kept by returning a null path.
      return null;
    }
    List<Pair<GraphNode, GraphEdgeInfo>> canonical = new ArrayList<>();
    while (path.path != null) {
      GraphNode source = path.node;
      if (source.isCycle()) {
        canonical.add(new Pair<>(source, new GraphEdgeInfo(EdgeKind.Unknown)));
      } else {
        GraphNode target = path.path.node;
        Set<GraphEdgeInfo> infos = getSourcesTargeting(target).get(source);
        canonical.add(new Pair<>(source, getCanonicalInfo(infos)));
      }
      path = path.path;
    }
    Set<GraphEdgeInfo> infos = getSourcesTargeting(endTarget).get(path.node);
    canonical.add(new Pair<>(path.node, getCanonicalInfo(infos)));
    return canonical;
  }

  // Compute the most meaningful edge reason.
  private GraphEdgeInfo getCanonicalInfo(Set<GraphEdgeInfo> infos) {
    // TODO(b/120959039): this is pretty bad...
    for (EdgeKind kind : EdgeKind.values()) {
      for (GraphEdgeInfo info : infos) {
        if (info.edgeKind() == kind) {
          return info;
        }
      }
    }
    assert false : "Unexpected empty set of graph edge info";
    return GraphEdgeInfo.unknown();
  }

  private void printEdge(GraphNode node, GraphEdgeInfo info, Formatter formatter) {
    formatter.addReason("is " + info.getInfoPrefix() + ":");
    addNodeMessage(node, formatter);
  }

  private String getNodeString(GraphNode node) {
    if (node instanceof ClassGraphNode) {
      return DescriptorUtils.descriptorToJavaType(
          ((ClassGraphNode) node).getReference().getDescriptor());
    }
    if (node instanceof MethodGraphNode) {
      MethodReference method = ((MethodGraphNode) node).getReference();
      return (method.getReturnType() == null ? "void" : method.getReturnType().getTypeName())
          + ' '
          + method.getHolderClass().getTypeName()
          + '.'
          + method.getMethodName()
          + StringUtils.join(
              ",",
              ListUtils.map(method.getFormalTypes(), TypeReference::getTypeName),
              BraceType.PARENS);
    }
    if (node instanceof FieldGraphNode) {
      FieldReference field = ((FieldGraphNode) node).getReference();
      return field.getFieldType().getTypeName()
          + ' '
          + field.getHolderClass().getTypeName()
          + '.'
          + field.getFieldName();
    }
    if (node instanceof KeepRuleGraphNode) {
      KeepRuleGraphNode keepRuleNode = (KeepRuleGraphNode) node;
      return keepRuleNode.getOrigin() == Origin.unknown()
          ? keepRuleNode.getContent()
          : keepRuleNode.getOrigin() + ":" + shortPositionInfo(keepRuleNode.getPosition());
    }
    if (node == GraphNode.cycle()) {
      return "only cyclic dependencies remain, failed to determine a path from a keep rule";
    }
    assert false : "Unexpected graph node type: " + node;
    return Objects.toString(node);
  }

  private void addNodeMessage(GraphNode node, Formatter formatter) {
    for (String line : StringUtils.splitLines(getNodeString(node))) {
      formatter.addMessage(line);
    }
  }

  private static String shortPositionInfo(Position position) {
    if (position instanceof TextRange) {
      TextPosition start = ((TextRange) position).getStart();
      return start.getLine() + ":" + start.getColumn();
    }
    return position.getDescription();
  }

  private static class Formatter {
    private final PrintStream output;
    private int indentation = -1;

    public Formatter(PrintStream output) {
      this.output = output;
    }

    void startItem(String itemString) {
      indentation++;
      indent();
      output.println(itemString);
    }

    private void indent() {
      for (int i = 0; i < indentation; i++) {
        output.print("  ");
      }
    }

    void addReason(String thing) {
      indent();
      output.print("|- ");
      output.println(thing);
    }

    void addMessage(String thing) {
      indent();
      output.print("|  ");
      output.println(thing);
    }

    void endItem() {
      indentation--;
    }
  }
}
