// 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.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.Box;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import java.io.ByteArrayInputStream;
import java.io.IOException;
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).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() throws ResourceException {
        return Collections.emptyList();
      }

      @Override
      public DataResourceProvider getDataResourceProvider() {
        return new DataResourceProvider() {
          @Override
          public void accept(Visitor visitor) throws ResourceException {
            visitor.visit(
                new DataEntryResource() {
                  @Override
                  public InputStream getByteStream() throws ResourceException {
                    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) {
        try {
          return ProgramResource.fromBytes(
              origin(clazz.getTypeName()),
              Kind.CF,
              ToolHelper.getClassAsBytes(clazz),
              getClassDescriptors());
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
      }
    };
  }

  public static class A {}

  public static class B {}

  public static class C {}
}
