// Copyright (c) 2017, 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.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

class UnusedItemsPrinter {

  private static class Members {
    final List<DexEncodedField> fields = new ArrayList<>();
    final List<DexEncodedMethod> methods = new ArrayList<>();

    boolean hasMembers() {
      return !fields.isEmpty() || !methods.isEmpty();
    }

    void sort() {
      fields.sort((a, b) -> a.getReference().compareTo(b.getReference()));
      methods.sort((a, b) -> a.getReference().compareTo(b.getReference()));
    }
  }

  private static final String INDENT = "    ";

  static final UnusedItemsPrinter DONT_PRINT = new NopPrinter();

  private final Consumer<String> consumer;

  private DexType currentType = null;
  private Members currentMembers = new Members();

  private List<Pair<DexType, Members>> classes = new ArrayList<>();

  UnusedItemsPrinter(Consumer<String> consumer) {
    this.consumer = consumer;
  }

  void registerUnusedClass(DexProgramClass clazz) {
    assert currentType == null;
    classes.add(new Pair<>(clazz.type, null));
  }

  // Visiting methods and fields of the given clazz.
  void visiting(DexProgramClass clazz) {
    assert currentType == null;
    currentType = clazz.type;
  }

  // Visited methods and fields of the top at the clazz stack.
  void visited() {
    if (currentMembers.hasMembers()) {
      classes.add(new Pair<>(currentType, currentMembers));
      currentMembers = new Members();
    }
    currentType = null;
  }

  void registerUnusedMethod(DexEncodedMethod method) {
    currentMembers.methods.add(method);
  }

  void registerUnusedField(DexEncodedField field) {
    currentMembers.fields.add(field);
  }

  public void finished() {
    classes.sort((a, b) -> a.getFirst().compareTo(b.getFirst()));
    for (Pair<DexType, Members> entry : classes) {
      DexType type = entry.getFirst();
      Members members = entry.getSecond();
      consumer.accept(type.toSourceString());
      if (members == null) {
        consumer.accept(StringUtils.LINE_SEPARATOR);
      } else {
        consumer.accept(":" + StringUtils.LINE_SEPARATOR);
        members.sort();
        members.fields.forEach(this::printUnusedField);
        members.methods.forEach(this::printUnusedMethod);
      }
    }
    classes = null;
  }

  private void append(String string) {
    consumer.accept(string);
  }

  private void newline() {
    append(StringUtils.LINE_SEPARATOR);
  }

  private void printUnusedMethod(DexEncodedMethod method) {
    append(INDENT);
    String accessFlags = method.accessFlags.toString();
    if (!accessFlags.isEmpty()) {
      append(accessFlags);
      append(" ");
    }
    append(method.getReference().proto.returnType.toSourceString());
    append(" ");
    append(method.getReference().name.toSourceString());
    append("(");
    for (int i = 0; i < method.getReference().proto.parameters.values.length; i++) {
      if (i != 0) {
        append(",");
      }
      append(method.getReference().proto.parameters.values[i].toSourceString());
    }
    append(")");
    newline();
  }

  private void printUnusedField(DexEncodedField field) {
    append(INDENT);
    String accessFlags = field.accessFlags.toString();
    if (!accessFlags.isEmpty()) {
      append(accessFlags);
      append(" ");
    }
    append(field.getReference().type.toSourceString());
    append(" ");
    append(field.getReference().name.toSourceString());
    newline();
  }

  // Empty implementation to silently ignore printing dead code.
  private static class NopPrinter extends UnusedItemsPrinter {

    public NopPrinter() {
      super(null);
    }

    @Override
    void registerUnusedClass(DexProgramClass clazz) {
      // Intentionally left empty.
    }

    @Override
    void visiting(DexProgramClass clazz) {
      // Intentionally left empty.
    }

    @Override
    void visited() {
      // Intentionally left empty.
    }

    @Override
    void registerUnusedMethod(DexEncodedMethod method) {
      // Intentionally left empty.
    }

    @Override
    void registerUnusedField(DexEncodedField field) {
      // Intentionally left empty.
    }

    @Override
    public void finished() {
      // Intentionally left empty.
    }
  }
}
