// Copyright (c) 2019, 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;

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

import com.android.tools.r8.DataResourceProvider.Visitor;
import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.dex.Marker;
import com.android.tools.r8.dex.Marker.Tool;
import com.android.tools.r8.dump.DumpOptions;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.internal.Box;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class AndroidAppDumpsTest extends TestBase {

  @Parameterized.Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withNoneRuntime().build();
  }

  public AndroidAppDumpsTest(TestParameters parameters) {
    parameters.assertNoneRuntime();
  }

  @Test
  public void test() throws Exception {
    InternalOptions options = new InternalOptions();
    options.dumpOptions = DumpOptions.builder(Tool.D8).setBackend(Marker.Backend.DEX).build();

    String dataResourceName = "my-resource.bin";
    byte[] dataResourceData = new byte[] {1, 2, 3};

    Path dexForB =
        testForD8().addProgramClasses(B.class).setMinApi(AndroidApiLevel.B).compile().writeToZip();

    AndroidApp appIn =
        AndroidApp.builder(options.reporter)
            .addClassProgramData(ToolHelper.getClassAsBytes(A.class), origin("A"))
            .addClassProgramData(ToolHelper.getClassAsBytes(A.class), origin("A"))
            .addClassProgramData(ToolHelper.getClassAsBytes(A.class), origin("A"))
            .addProgramFile(dexForB)
            .addClasspathResourceProvider(provider(B.class))
            .addClasspathResourceProvider(provider(B.class))
            .addClasspathResourceProvider(provider(B.class))
            .addLibraryResourceProvider(provider(C.class))
            .addLibraryResourceProvider(provider(C.class))
            .addLibraryResourceProvider(provider(C.class))
            .addProgramResourceProvider(
                createDataResourceProvider(
                    dataResourceName, dataResourceData, origin(dataResourceName)))
            .build();

    Path dumpFile = temp.newFolder().toPath().resolve("dump.zip");
    appIn.dump(dumpFile, options.dumpOptions, options);

    AndroidApp appOut = AndroidApp.builder(options.reporter).addDump(dumpFile).build();
    assertEquals(1, appOut.getClassProgramResourcesForTesting().size());
    assertEquals(
        DescriptorUtils.javaTypeToDescriptor(A.class.getTypeName()),
        appOut.getClassProgramResourcesForTesting().get(0).getClassDescriptors().iterator().next());

    assertEquals(1, appOut.getDexProgramResourcesForTesting().size());

    assertEquals(1, appOut.getClasspathResourceProviders().size());
    assertEquals(
        DescriptorUtils.javaTypeToDescriptor(B.class.getTypeName()),
        appOut.getClasspathResourceProviders().get(0).getClassDescriptors().iterator().next());

    assertEquals(1, appOut.getLibraryResourceProviders().size());
    assertEquals(
        DescriptorUtils.javaTypeToDescriptor(C.class.getTypeName()),
        appOut.getLibraryResourceProviders().get(0).getClassDescriptors().iterator().next());

    Box<Boolean> foundData = new Box<>(false);
    for (ProgramResourceProvider provider : appOut.getProgramResourceProviders()) {
      DataResourceProvider dataProvider = provider.getDataResourceProvider();
      if (dataProvider != null) {
        dataProvider.accept(
            new Visitor() {
              @Override
              public void visit(DataDirectoryResource directory) {}

              @Override
              public void visit(DataEntryResource file) {
                if (file.getName().equals(dataResourceName)) {
                  foundData.set(true);
                }
              }
            });
      }
    }
    assertTrue(foundData.get());
  }

  private ProgramResourceProvider createDataResourceProvider(
      String name, byte[] content, Origin origin) {
    return new ProgramResourceProvider() {
      @Override
      public Collection<ProgramResource> getProgramResources() {
        return Collections.emptyList();
      }

      @Override
      public DataResourceProvider getDataResourceProvider() {
        return new DataResourceProvider() {
          @Override
          public void accept(Visitor visitor) {
            visitor.visit(
                new DataEntryResource() {
                  @Override
                  public InputStream getByteStream() {
                    return new ByteArrayInputStream(content);
                  }

                  @Override
                  public String getName() {
                    return name;
                  }

                  @Override
                  public Origin getOrigin() {
                    return origin;
                  }
                });
          }
        };
      }
    };
  }

  private Origin origin(String name) {
    return new Origin(Origin.root()) {
      @Override
      public String part() {
        return name;
      }
    };
  }

  private ClassFileResourceProvider provider(Class<?> clazz) {
    return new ClassFileResourceProvider() {
      @Override
      public Set<String> getClassDescriptors() {
        return Collections.singleton(DescriptorUtils.javaTypeToDescriptor(clazz.getTypeName()));
      }

      @Override
      public ProgramResource getProgramResource(String descriptor) {
          return ProgramResource.fromBytes(
              origin(clazz.getTypeName()),
              Kind.CF,
              ToolHelper.getClassAsBytes(clazz),
              getClassDescriptors());
      }
    };
  }

  public static class A {}

  public static class B {}

  public static class C {}
}
