// 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 com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.DescriptorUtils;
import com.google.common.collect.ImmutableMap;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public abstract class TestBaseBuilder<
        C extends BaseCommand,
        B extends BaseCommand.Builder<C, B>,
        CR extends TestBaseResult<CR, RR>,
        RR extends TestRunResult<RR>,
        T extends TestBaseBuilder<C, B, CR, RR, T>>
    extends TestBuilder<RR, T> {

  final B builder;

  TestBaseBuilder(TestState state, B builder) {
    super(state);
    this.builder = builder;
  }

  @Override
  public T addProgramClassFileData(Collection<byte[]> classes) {
    for (byte[] clazz : classes) {
      builder.addClassProgramData(clazz, Origin.unknown());
    }
    return self();
  }

  @Override
  public T addProgramDexFileData(Collection<byte[]> data) {
    for (byte[] dex : data) {
      builder.addDexProgramData(dex, Origin.unknown());
    }
    return self();
  }

  @Override
  public T addProgramFiles(Collection<Path> files) {
    builder.addProgramFiles(files);
    return self();
  }

  public T addLibraryProvider(ClassFileResourceProvider provider) {
    builder.addLibraryResourceProvider(provider);
    return self();
  }

  @Override
  public T addLibraryFiles(Collection<Path> files) {
    builder.addLibraryFiles(files);
    return self();
  }

  @Override
  public T addLibraryClasses(Collection<Class<?>> classes) {
    builder.addLibraryResourceProvider(ClassFileResourceProviderFromClasses(classes));
    return self();
  }

  public T addMainDexListClasses(Class<?>... classes) {
    return addMainDexListClasses(Arrays.asList(classes));
  }

  public T addMainDexListClasses(Collection<Class<?>> classes) {
    builder.addMainDexClasses(
        classes.stream().map(Class::getTypeName).collect(Collectors.toList()));
    return self();
  }

  public T addMainDexListFiles(Collection<Path> files) {
    builder.addMainDexListFiles(files);
    return self();
  }

  public static ClassFileResourceProvider ClassFileResourceProviderFromClasses(
      Collection<Class<?>> classes) {
    return new ClassFileResourceProvider() {
      final Map<String, ProgramResource> resources;

      {
        ImmutableMap.Builder<String, ProgramResource> builder = ImmutableMap.builder();
        classes.forEach(
            c ->
                builder.put(
                    DescriptorUtils.javaTypeToDescriptor(c.getTypeName()),
                    ProgramResource.fromFile(Kind.CF, ToolHelper.getClassFileForTestClass(c))));
        resources = builder.build();
      }

      @Override
      public Set<String> getClassDescriptors() {
        return resources.keySet();
      }

      @Override
      public ProgramResource getProgramResource(String descriptor) {
        return resources.get(descriptor);
      }
    };
  }
}
