// Copyright (c) 2016, 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.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexDefinition;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItem;
import com.android.tools.r8.graph.DexType;
import com.google.common.collect.Sets;
import java.io.PrintStream;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Collections;
import java.util.Deque;
import java.util.Map;
import java.util.Set;

public class ReasonPrinter {

  private final Set<DexDefinition> itemsQueried;
  private ReasonFormatter formatter;

  private final Map<DexEncodedField, KeepReason> liveFields;
  private final Map<DexEncodedMethod, KeepReason> liveMethods;
  private final Map<DexDefinition, KeepReason> reachablityReasons;
  private final Map<DexType, KeepReason> instantiatedTypes;

  ReasonPrinter(Set<DexDefinition> itemsQueried, Map<DexEncodedField, KeepReason> liveFields,
      Map<DexEncodedMethod, KeepReason> liveMethods, Map<DexDefinition, KeepReason> reachablityReasons,
      Map<DexType, KeepReason> instantiatedTypes) {
    this.itemsQueried = itemsQueried;
    this.liveFields = liveFields;
    this.liveMethods = liveMethods;
    this.reachablityReasons = reachablityReasons;
    this.instantiatedTypes = instantiatedTypes;
  }

  public void run(DexApplication application) {
    // TODO(herhut): Instead of traversing the app, sort the queried items.
    formatter = new ReasonFormatter();
    for (DexClass clazz : application.classes()) {
      if (itemsQueried.contains(clazz)) {
        printReasonFor(clazz);
      }
      Arrays.stream(clazz.staticFields()).filter(itemsQueried::contains)
          .forEach(this::printReasonFor);
      Arrays.stream(clazz.instanceFields()).filter(itemsQueried::contains)
          .forEach(this::printReasonFor);
      Arrays.stream(clazz.directMethods()).filter(itemsQueried::contains)
          .forEach(this::printReasonFor);
      Arrays.stream(clazz.virtualMethods()).filter(itemsQueried::contains)
          .forEach(this::printReasonFor);
    }
  }

  private void printNoIdeaWhy(DexItem item, ReasonFormatter formatter) {
    formatter.startItem(item);
    formatter.pushEmptyPrefix();
    formatter.addReason("is kept for unknown reason.");
    formatter.popPrefix();
    formatter.endItem();
  }

  private void printOnlyAbstractShell(DexItem item, ReasonFormatter formatter) {
    formatter.startItem(item);
    KeepReason reachableReason = reachablityReasons.get(item);
    if (reachableReason != null) {
      formatter.pushPrefix(
          "is not kept, only its abstract declaration is needed because it ");
      reachableReason.print(formatter);
      formatter.popPrefix();
    } else {
      formatter.pushEmptyPrefix();
      formatter.addReason("is not kept, only its abstract declaration is.");
      formatter.popPrefix();
    }
    formatter.endItem();
  }

  private void printReasonFor(DexClass item) {
    KeepReason reason = instantiatedTypes.get(item.type);
    if (reason == null) {
      if (item.accessFlags.isAbstract()) {
        printOnlyAbstractShell(item, formatter);
      } else {
        printNoIdeaWhy(item, formatter);
      }
    } else {
      formatter.startItem(item);
      formatter.pushIsLivePrefix();
      reason.print(formatter);
      formatter.popPrefix();
      formatter.endItem();
    }
  }

  private void printReasonFor(DexEncodedMethod item) {
    KeepReason reasonLive = liveMethods.get(item);
    if (reasonLive == null) {
      if (item.accessFlags.isAbstract()) {
        printOnlyAbstractShell(item, formatter);
      } else {
        printNoIdeaWhy(item.method, formatter);
      }
    } else {
      formatter.addMethodReferenceReason(item);
    }
  }

  private void printReasonFor(DexEncodedField item) {
    KeepReason reason = liveFields.get(item);
    if (reason == null) {
      printNoIdeaWhy(item.field, formatter);
    } else {
      formatter.startItem(item.field);
      formatter.pushIsLivePrefix();
      reason.print(formatter);
      formatter.popPrefix();
      reason = reachablityReasons.get(item);
      if (reason != null) {
        formatter.pushIsReachablePrefix();
        reason.print(formatter);
        formatter.popPrefix();
      }
      formatter.endItem();
    }
  }

  class ReasonFormatter {

    private final Set<DexItem> seen = Sets.newIdentityHashSet();
    private final Deque<String> prefixes = new ArrayDeque<>();

    private int indentation = -1;

    private PrintStream output = System.out;

    void pushIsLivePrefix() {
      prefixes.push("is live because ");
    }

    void pushIsReachablePrefix() {
      prefixes.push("is reachable because ");
    }

    void pushPrefix(String prefix) {
      prefixes.push(prefix);
    }

    void pushEmptyPrefix() {
      prefixes.push("");
    }

    void popPrefix() {
      prefixes.pop();
    }

    void startItem(DexItem item) {
      indentation++;
      indent();
      output.println(item.toSourceString());
    }

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

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

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

    void endItem() {
      indentation--;
    }

    void addMethodReferenceReason(DexEncodedMethod method) {
      if (!seen.add(method.method)) {
        return;
      }
      startItem(method);
      KeepReason reason = reachablityReasons.get(method);
      if (reason != null) {
        pushIsReachablePrefix();
        reason.print(this);
        popPrefix();
      }
      reason = liveMethods.get(method);
      if (reason != null) {
        pushIsLivePrefix();
        reason.print(this);
        popPrefix();
      }
      endItem();
    }

    void addTypeLivenessReason(DexType type) {
      if (!seen.add(type)) {
        return;
      }
      startItem(type);
      pushIsLivePrefix();
      KeepReason reason = instantiatedTypes.get(type);
      if (reason != null) {
        reason.print(this);
      }
      popPrefix();
      endItem();
    }
  }

  public static ReasonPrinter getNoOpPrinter() {
    return new NoOpReasonPrinter();
  }

  private static class NoOpReasonPrinter extends ReasonPrinter {

    NoOpReasonPrinter() {
      super(Collections.emptySet(), Collections.emptyMap(), Collections.emptyMap(),
          Collections.emptyMap(), Collections.emptyMap());
    }

    @Override
    public void run(DexApplication application) {
      // Intentionally left empty.
    }
  }
}
