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

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.DexInstructionSubject;
import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
import com.android.tools.r8.utils.codeinspector.FoundFieldSubject;
import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import org.junit.Ignore;
import org.junit.Test;

// A comparator that inputs two apks you want to investigate, along with mappings if available.
// This will help you walk through apks in a fancy IDE debugging mode.
public class AppComparator extends TestBase {
  // Update the following path strings to point to apks you are inspecting.
  private static final String PATH_0 = "/path/to/workspace";
  private static final String PATH_1 = PATH_0 + "/R8.apk";
  private static final String PATH_2 = PATH_0 + "/proguard.apk";
  private static final String MAP_1 = PATH_0 + "/mapping-R8.txt";
  private static final String MAP_2 = PATH_0 + "/mapping-proguard.txt";

  private static final boolean allowMissingClassInApp2 = true;

  private AndroidApp loadApp(String path) {
    AndroidApp.Builder builder = AndroidApp.builder();
    builder.addProgramFile(Paths.get(path));
    return builder.build();
  }

  @Ignore("Comment out this to run locally.")
  @Test
  public void identicalTest_specificMethods() throws Exception {
    AndroidApp app1 = loadApp(PATH_1);
    AndroidApp app2 = loadApp(PATH_2);

    CodeInspector inspect1 = new CodeInspector(app1, Paths.get(MAP_1));
    CodeInspector inspect2 = new CodeInspector(app2, Paths.get(MAP_2));

    // Define your own tester to pick methods to inspect.
    Predicate<DexEncodedMethod> methodTester = encodedMethod -> {
      return encodedMethod.method.name.toString().equals("run")
          && encodedMethod.method.getArity() == 0;
    };

    inspect1.forAllClasses(clazz1 -> {
      clazz1.forAllMethods(method1 -> {
        if (methodTester.test(method1.getMethod())) {
          ClassSubject clazz2 = inspect2.clazz(clazz1.getOriginalName());
          if (!clazz2.isPresent()) {
            String classNotFound =
                String.format("Class %s not found in app2", clazz1.getOriginalName());
            if (allowMissingClassInApp2) {
              System.out.println(classNotFound);
              return;
            }
            assertThat(classNotFound, clazz2, isPresent());
          }
          MethodSubject method2 = clazz2.method(method1.getOriginalSignature());
          if (!method2.isPresent()) {
            method2 = clazz2.method(method1.getFinalSignature());
          }
          if (!method2.isPresent()) {
            assertThat(String.format("Method %s not found in app2", method1.getFinalSignature()),
                method2, isPresent());
          }
          if (method1.getMethod().shouldNotHaveCode()) {
            assertTrue(method2.getMethod().shouldNotHaveCode());
            return;
          }
          if (!identicalCode(method1, method2)) {
            System.out.println("Found different method body: ");
            System.out.println(method1.getMethod().codeToString());
            System.out.println(method2.getMethod().codeToString());
          }
        }
      });
    });
  }

  @Ignore("Comment out this to run locally.")
  @Test
  public void identicalTest_wholeApp() throws Exception {
    // Set to false to not compare the code, but only the structure.
    boolean compareInstructions = true;

    AndroidApp app1 = loadApp(PATH_1);
    AndroidApp app2 = loadApp(PATH_2);

    CodeInspector inspect1 = new CodeInspector(app1);
    CodeInspector inspect2 = new CodeInspector(app2);

    class Pair<T> {
      private T first;
      private T second;

      private void set(boolean selectFirst, T value) {
        if (selectFirst) {
          first = value;
        } else {
          second = value;
        }
      }
    }

    // Collect all classes from both inspectors, indexed by finalDescriptor.
    Map<String, Pair<FoundClassSubject>> allClasses = new HashMap<>();

    BiConsumer<CodeInspector, Boolean> collectClasses = (inspector, selectFirst) -> {
      inspector.forAllClasses(
          clazz -> {
            String finalDescriptor = clazz.getFinalDescriptor();
            allClasses.compute(
                finalDescriptor,
                (k, v) -> {
                  if (v == null) {
                    v = new Pair<>();
                  }
                  v.set(selectFirst, clazz);
                  return v;
                });
          });
    };

    collectClasses.accept(inspect1, true);
    collectClasses.accept(inspect2, false);

    for (Map.Entry<String, Pair<FoundClassSubject>> classEntry : allClasses.entrySet()) {
      String className = classEntry.getKey();
      FoundClassSubject class1 = classEntry.getValue().first;
      FoundClassSubject class2 = classEntry.getValue().second;

      assert class1 != null || class2 != null;

      assertNotNull(String.format("Class %s is missing from the first app.", className), class1);
      assertNotNull(String.format("Class %s is missing from the second app.", className), class2);

      // Collect all fields for this class from both apps.
      Map<FieldSignature, Pair<FoundFieldSubject>> allFields = new HashMap<>();

      BiConsumer<FoundClassSubject, Boolean> collectFields = (classSubject, selectFirst) -> {
        classSubject.forAllFields(
            f -> {
              FieldSignature fs = f.getFinalSignature();
              allFields.compute(
                  fs,
                  (k, v) -> {
                    if (v == null) {
                      v = new Pair<>();
                    }
                    v.set(selectFirst, f);
                    return v;
                  });
            });
      };

      collectFields.accept(class1, true);
      collectFields.accept(class2, false);

      for (Map.Entry<FieldSignature, Pair<FoundFieldSubject>> fieldEntry : allFields.entrySet()) {
        FieldSignature signature = fieldEntry.getKey();
        FoundFieldSubject field1 = fieldEntry.getValue().first;
        FoundFieldSubject field2 = fieldEntry.getValue().second;
        assert field1 != null || field2 != null;

        assertNotNull(
            String.format(
                "Field %s of class %s is missing from the first app.", signature, className),
            field1);
        assertNotNull(
            String.format(
                "Field %s of class %s is missing from the second app.", signature, className),
            field2);
      }

      // Collect all methods for this class from both apps.
      Map<MethodSignature, Pair<FoundMethodSubject>> allMethods = new HashMap<>();

      BiConsumer<FoundClassSubject, Boolean> collectMethods = (classSubject, selectFirst) -> {
        classSubject.forAllMethods(
            m -> {
              MethodSignature fs = m.getFinalSignature();
              allMethods.compute(
                  fs,
                  (k, v) -> {
                    if (v == null) {
                      v = new Pair<>();
                    }
                    v.set(selectFirst, m);
                    return v;
                  });
            });
      };

      collectMethods.accept(class1, true);
      collectMethods.accept(class2, false);

      List<FoundMethodSubject> methodsNotMatching = new ArrayList<>();
      for (Map.Entry<MethodSignature, Pair<FoundMethodSubject>> methodEntry :
          allMethods.entrySet()) {
        MethodSignature signature = methodEntry.getKey();
        FoundMethodSubject method1 = methodEntry.getValue().first;
        FoundMethodSubject method2 = methodEntry.getValue().second;
        assert method1 != null || method2 != null;

        assertNotNull(
            String.format(
                "Method %s of class %s is missing from the first app.", signature, className),
            method1);
        assertNotNull(
            String.format(
                "Method %s of class %s is missing from the second app.", signature, className),
            method2);

        if (method1.getMethod().shouldNotHaveCode()) {
          assertTrue(method2.getMethod().shouldNotHaveCode());
          continue;
        }

        // Even compare every single instruction. Adjust for your own purpose or comment out.
        if (compareInstructions) {
          if (!identicalCode(method1, method2)) {
            System.out.println("Full method for " + method1.toString() + ": ");
            methodsNotMatching.add(method1);
            methodsNotMatching.add(method2);
          }
        }
      }
      if (!methodsNotMatching.isEmpty()) {
        System.out.println("-------------------------------------");
        for (int i = 0; i < methodsNotMatching.size(); i += 2) {
          FoundMethodSubject method1 = methodsNotMatching.get(i);
          FoundMethodSubject method2 = methodsNotMatching.get(i +  1);
          System.out.println("Full method for " + method1.toString() + ": ");
          System.out.println(method1.getMethod().codeToString());
          System.out.println(method2.getMethod().codeToString());
        }
      }
    }
  }

  private boolean identicalCode(MethodSubject method1, MethodSubject method2) {
    Iterator<InstructionSubject> it1 = method1.iterateInstructions();
    Iterator<InstructionSubject> it2 = method2.iterateInstructions();
    boolean identical = true;
    while (it1.hasNext()) {
      assertTrue(it2.hasNext());
      InstructionSubject instr1 = it1.next();
      InstructionSubject instr2 = it2.next();
      assertEquals(
          instr1 instanceof DexInstructionSubject,
          instr2 instanceof DexInstructionSubject);
      if (!instr1.equals(instr2)) {
        if (identical) {
          System.out.println("DIFF in " + method1.toString() + ":");
        }
        System.out.println("< " + instr1);
        System.out.println("> " + instr2);
        identical = false;
      }
    }
    return identical;
  }
}
