// 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.debuginfo;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexDebugEntry;
import com.android.tools.r8.graph.DexDebugEntryBuilder;
import com.android.tools.r8.graph.DexDebugInfo;
import com.android.tools.r8.graph.DexDebugInfo.EventBasedDebugInfo;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import java.util.stream.Collectors;

public class DebugInfoInspector {

  // Method kept here to aid inspection when debugging the tests.
  private final DexEncodedMethod method;
  private final List<DexDebugEntry> entries;

  final EventBasedDebugInfo info;

  public DebugInfoInspector(DexEncodedMethod method, DexItemFactory factory) {
    this.method = method;
    EventBasedDebugInfo debugInfo =
        DexDebugInfo.convertToEventBased(method.getCode().asDexCode(), factory);
    if (debugInfo != null) {
      info = debugInfo;
      entries = new DexDebugEntryBuilder(method, factory).build();
      checkConsistentEntries();
    } else {
      info = null;
      entries = Collections.emptyList();
    }
  }

  public DebugInfoInspector(CodeInspector inspector, String clazz, MethodSignature method) {
    this(inspector.clazz(clazz).method(method).getMethod(), inspector.getFactory());
  }

  public DebugInfoInspector(AndroidApp app, String clazz, MethodSignature method)
      throws IOException, ExecutionException {
    this(new CodeInspector(app), clazz, method);
  }

  public void checkStartLine(int i) {
    assertEquals(i, info.startLine);
  }

  public int checkLineExists(int line) {
    int lines = checkLines(line, entry -> {});
    assertTrue(lines > 0);
    return lines;
  }

  public int checkLineHasExactLocals(int line, String... pairs) {
    int lines = checkLines(line, entry -> checkLocalsEqual(entry, pairs));
    assertTrue("Failed to find entry for line " + line, lines > 0);
    return lines;
  }

  public int checkLineHasNoLocals(int line) {
    return checkLineHasExactLocals(line);
  }

  public int checkLineHasAtLeastLocals(int line, String... pairs) {
    int lines = checkLines(line, entry -> checkLocalsDefined(entry, pairs));
    assertTrue("No entries found for line: " + line, lines > 0);
    return lines;
  }

  public void checkNoLine(int line) {
    int lines = checkLines(line, entry -> {});
    assertEquals(0, lines);
  }

  public int checkLineHasLocal(int line, String name, String type, String... typeParameters) {
    int lines = checkLines(line, entry -> {
      checkLocalDefined(entry, name, type, typeParameters);
    });
    assertTrue(lines > 0);
    return lines;
  }

  @Override
  public String toString() {
    StringBuilder builder = new StringBuilder();
    for (DexDebugEntry entry : entries) {
      builder.append(entry).append("\n");
    }
    return builder.toString();
  }

  private void checkConsistentEntries() {
    DexDebugEntry previousLineEntry = null;
    for (DexDebugEntry entry : entries) {
      if (entry.lineEntry) {
        assertTrue(
            "More than one entry defined for PC " + StringUtils.hexString(entry.address, 2),
            previousLineEntry == null || entry.address > previousLineEntry.address);
        previousLineEntry = entry;
      }
    }
  }

  private int checkLines(int line, Consumer<DexDebugEntry> check) {
    int found = 0;
    for (int i = 0; i < entries.size(); i++) {
      DexDebugEntry entry = entries.get(i);
      // Matches each entry at 'line' that is not a zero-line increment.
      if (entry.getLine() == line && (i == 0 || entries.get(i - 1).getLine() != line)) {
        found++;
        check.accept(entry);
      }
    }
    return found;
  }

  private static DebugLocalInfo checkLocalDefined(DexDebugEntry entry, String name, String type,
      String... typeParameters) {
    DebugLocalInfo found = null;
    for (DebugLocalInfo local : entry.locals.values()) {
      if (local.name.toString().equals(name)) {
        if (found != null) {
          fail(
              "Line "
                  + entry.getPosition().getLine()
                  + ". Local defined multiple times for name: "
                  + name);
        }
        assertEquals(type, local.type.toString());
        if (typeParameters.length > 0) {
          String desc = DescriptorUtils.javaTypeToDescriptor(type);
          StringBuilder builder = new StringBuilder(desc.substring(0, desc.length() - 1));
          builder.append("<");
          for (String parameter : typeParameters) {
            builder.append(parameter);
          }
          builder.append(">;");
          assertEquals(builder.toString(), local.signature.toString());
        }
        found = local;
      }
    }
    assertNotNull("Line " + entry.getLine() + ". Failed to find local with name: " + name, found);
    return found;
  }

  private static void checkLocalsDefined(DexDebugEntry entry, String... pairs) {
    assert pairs.length % 2 == 0;
    for (int i = 0; i < pairs.length; i += 2) {
      checkLocalDefined(entry, pairs[i], pairs[i + 1]);
    }
  }

  private static void checkLocalsEqual(DexDebugEntry entry, String[] pairs) {
    assert pairs == null || pairs.length % 2 == 0;
    int expected = pairs == null ? 0 : pairs.length / 2;
    Set<DebugLocalInfo> remaining = new HashSet<>(entry.locals.values());
    if (pairs != null) {
      for (int i = 0; i < pairs.length; i += 2) {
        DebugLocalInfo local = checkLocalDefined(entry, pairs[i], pairs[i + 1]);
        remaining.remove(local);
      }
    }
    assertEquals(
        "Line "
            + entry.getLine()
            + ". Found unexpected locals: "
            + String.join(
                ",", remaining.stream().map(Object::toString).collect(Collectors.toList())),
        expected,
        expected + remaining.size());
  }

  public DexEncodedMethod getMethod() {
    return method;
  }

  public List<DexDebugEntry> getEntries() {
    return entries;
  }
}
