// Copyright (c) 2020, 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.tracereferences;

import static com.android.tools.r8.utils.FileUtils.isArchive;
import static com.android.tools.r8.utils.FileUtils.isClassFile;
import static com.android.tools.r8.utils.FileUtils.isDexFile;
import static com.android.tools.r8.utils.InternalOptions.ASM_VERSION;

import com.android.tools.r8.ArchiveClassFileProvider;
import com.android.tools.r8.ClassFileResourceProvider;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.Diagnostic;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.Keep;
import com.android.tools.r8.ProgramResource;
import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.ProgramResourceProvider;
import com.android.tools.r8.ResourceException;
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.origin.PathOrigin;
import com.android.tools.r8.utils.ArchiveResourceProvider;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.ExceptionDiagnostic;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;

@Keep
public class TraceReferencesCommand {
  private final boolean printHelp;
  private final boolean printVersion;
  private final Reporter reporter;
  private final ImmutableList<ClassFileResourceProvider> library;
  private final ImmutableList<ClassFileResourceProvider> traceTarget;
  private final ImmutableList<ProgramResourceProvider> traceSource;
  private final TraceReferencesConsumer consumer;

  TraceReferencesCommand(
      boolean printHelp,
      boolean printVersion,
      Reporter reporter,
      ImmutableList<ClassFileResourceProvider> library,
      ImmutableList<ClassFileResourceProvider> traceTarget,
      ImmutableList<ProgramResourceProvider> traceSource,
      TraceReferencesConsumer consumer) {
    this.printHelp = printHelp;
    this.printVersion = printVersion;
    this.reporter = reporter;
    this.library = library;
    this.traceTarget = traceTarget;
    this.traceSource = traceSource;
    this.consumer = consumer;
  }

  TraceReferencesCommand(boolean printHelp, boolean printVersion) {
    this.printHelp = printHelp;
    this.printVersion = printVersion;
    this.reporter = null;
    this.library = null;
    this.traceTarget = null;
    this.traceSource = null;
    this.consumer = null;
  }

  /**
   * Utility method for obtaining a <code>ReferenceTraceCommand.Builder</code>.
   *
   * @param diagnosticsHandler The diagnostics handler for consuming messages.
   */
  public static Builder builder(DiagnosticsHandler diagnosticsHandler) {
    return new Builder(diagnosticsHandler);
  }

  /**
   * Utility method for obtaining a <code>ReferenceTraceCommand.Builder</code> with a default
   * diagnostics handler.
   */
  public static Builder builder() {
    return new Builder();
  }

  public static Builder parse(String[] args, Origin origin) {
    return TraceReferencesCommandParser.parse(args, origin);
  }

  public static Builder parse(String[] args, Origin origin, DiagnosticsHandler diagnosticsHandler) {
    return TraceReferencesCommandParser.parse(args, origin, diagnosticsHandler);
  }

  public static Builder parse(Collection<String> args, Origin origin) {
    return TraceReferencesCommandParser.parse(args.toArray(new String[args.size()]), origin);
  }

  public boolean isPrintHelp() {
    return printHelp;
  }

  public boolean isPrintVersion() {
    return printVersion;
  }

  @Keep
  public static class Builder {

    private boolean printHelp = false;
    private boolean printVersion = false;
    private final Reporter reporter;
    private final ImmutableList.Builder<ClassFileResourceProvider> libraryBuilder =
        ImmutableList.builder();
    private final ImmutableList.Builder<ClassFileResourceProvider> traceTargetBuilder =
        ImmutableList.builder();
    private final ImmutableList.Builder<ProgramResourceProvider> traceSourceBuilder =
        ImmutableList.builder();
    private TraceReferencesConsumer consumer;

    private Builder() {
      this(new DiagnosticsHandler() {});
    }

    private Builder(DiagnosticsHandler diagnosticsHandler) {
      this.reporter = new Reporter(diagnosticsHandler);
    }

    Reporter getReporter() {
      return reporter;
    }

    /** True if the print-help flag is enabled. */
    public boolean isPrintHelp() {
      return printHelp;
    }

    /** Set the value of the print-help flag. */
    public Builder setPrintHelp(boolean printHelp) {
      this.printHelp = printHelp;
      return this;
    }

    /** True if the print-version flag is enabled. */
    public boolean isPrintVersion() {
      return printVersion;
    }

    /** Set the value of the print-version flag. */
    public Builder setPrintVersion(boolean printVersion) {
      this.printVersion = printVersion;
      return this;
    }

    private static String extractClassDescriptor(byte[] data) {
      class ClassNameExtractor extends ClassVisitor {
        private String className;

        private ClassNameExtractor() {
          super(ASM_VERSION);
        }

        @Override
        public void visit(
            int version,
            int access,
            String name,
            String signature,
            String superName,
            String[] interfaces) {
          className = name;
        }

        String getClassInternalType() {
          return className;
        }
      }

      ClassReader reader = new ClassReader(data);
      ClassNameExtractor extractor = new ClassNameExtractor();
      reader.accept(
          extractor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
      return "L" + extractor.getClassInternalType() + ";";
    }

    private static class SingleClassClassFileResourceProvider implements ClassFileResourceProvider {
      private final String descriptor;
      private final ProgramResource programResource;

      SingleClassClassFileResourceProvider(Origin origin, byte[] data) {
        this.descriptor = extractClassDescriptor(data);
        this.programResource =
            ProgramResource.fromBytes(origin, Kind.CF, data, ImmutableSet.of(descriptor));
      }

      @Override
      public Set<String> getClassDescriptors() {
        return ImmutableSet.of(descriptor);
      }

      @Override
      public ProgramResource getProgramResource(String descriptor) {
        return descriptor.equals(this.descriptor) ? programResource : null;
      }
    }

    private ClassFileResourceProvider singleClassFileClassFileResourceProvider(Path file)
        throws IOException {
      return new SingleClassClassFileResourceProvider(
          new PathOrigin(file), Files.readAllBytes(file));
    }

    private ProgramResourceProvider singleClassFileProgramResourceProvider(Path file)
        throws IOException {
      byte[] bytes = Files.readAllBytes(file);
      String descriptor = extractClassDescriptor(bytes);
      return new ProgramResourceProvider() {

        @Override
        public Collection<ProgramResource> getProgramResources() {
          return ImmutableList.of(
              ProgramResource.fromBytes(
                  new PathOrigin(file), Kind.CF, bytes, ImmutableSet.of(descriptor)));
        }
      };
    }

    private void addLibraryOrTargetFile(
        Path file, ImmutableList.Builder<ClassFileResourceProvider> builder) {
      if (!Files.exists(file)) {
        PathOrigin pathOrigin = new PathOrigin(file);
        NoSuchFileException noSuchFileException = new NoSuchFileException(file.toString());
        error(new ExceptionDiagnostic(noSuchFileException, pathOrigin));
      }
      if (isArchive(file)) {
        try {
          ArchiveClassFileProvider provider = new ArchiveClassFileProvider(file);
          builder.add(provider);
        } catch (IOException e) {
          error(new ExceptionDiagnostic(e, new PathOrigin(file)));
        }
      } else if (isClassFile(file)) {
        try {
          builder.add(singleClassFileClassFileResourceProvider(file));
        } catch (IOException e) {
          error(new ExceptionDiagnostic(e));
        }
      } else {
        error(new StringDiagnostic("Unsupported source file type", new PathOrigin(file)));
      }
    }

    private void addSourceFile(Path file) {
      if (!Files.exists(file)) {
        PathOrigin pathOrigin = new PathOrigin(file);
        NoSuchFileException noSuchFileException = new NoSuchFileException(file.toString());
        error(new ExceptionDiagnostic(noSuchFileException, pathOrigin));
      }
      if (isArchive(file)) {
        traceSourceBuilder.add(ArchiveResourceProvider.fromArchive(file, false));
      } else if (isClassFile(file)) {
        try {
          traceSourceBuilder.add(singleClassFileProgramResourceProvider(file));
        } catch (IOException e) {
          error(new ExceptionDiagnostic(e));
        }
      } else if (isDexFile(file)) {
        traceSourceBuilder.add(
            new ProgramResourceProvider() {
              ProgramResource dexResource = ProgramResource.fromFile(Kind.DEX, file);

              @Override
              public Collection<ProgramResource> getProgramResources() throws ResourceException {
                return Collections.singletonList(dexResource);
              }
            });
      } else {
        error(new StringDiagnostic("Unsupported source file type", new PathOrigin(file)));
      }
    }

    public Builder addLibraryResourceProvider(ClassFileResourceProvider provider) {
      libraryBuilder.add(provider);
      return this;
    }

    public Builder addLibraryFiles(Path... files) {
      addLibraryFiles(Arrays.asList(files));
      return this;
    }

    public Builder addLibraryFiles(Collection<Path> files) {
      for (Path file : files) {
        addLibraryOrTargetFile(file, libraryBuilder);
      }
      return this;
    }

    public Builder addTargetFiles(Path... files) {
      addTargetFiles(Arrays.asList(files));
      return this;
    }

    public Builder addTargetFiles(Collection<Path> files) {
      for (Path file : files) {
        addLibraryOrTargetFile(file, traceTargetBuilder);
      }
      return this;
    }

    public Builder addSourceFiles(Path... files) {
      addSourceFiles(Arrays.asList(files));
      return this;
    }

    public Builder addSourceFiles(Collection<Path> files) {
      for (Path file : files) {
        addSourceFile(file);
      }
      return this;
    }

    public Builder setConsumer(TraceReferencesConsumer consumer) {
      this.consumer = consumer;
      return this;
    }

    private TraceReferencesCommand makeCommand() {
      if (isPrintHelp() || isPrintVersion()) {
        return new TraceReferencesCommand(isPrintHelp(), isPrintVersion());
      }

      ImmutableList<ClassFileResourceProvider> library = libraryBuilder.build();
      ImmutableList<ClassFileResourceProvider> traceTarget = traceTargetBuilder.build();
      ImmutableList<ProgramResourceProvider> traceSource = traceSourceBuilder.build();

      if (library.isEmpty()) {
        error(new StringDiagnostic("No library specified"));
      }
      if (traceTarget.isEmpty()) {
        // Target can be empty for tracing references from source outside of library.
      }
      if (traceSource.isEmpty()) {
        error(new StringDiagnostic("No source specified"));
      }
      if (consumer == null) {
        error(new StringDiagnostic("No consumer specified"));
      }
      return new TraceReferencesCommand(
          printHelp, printVersion, reporter, library, traceTarget, traceSource, consumer);
    }

    public final TraceReferencesCommand build() throws CompilationFailedException {
      Box<TraceReferencesCommand> box = new Box<>(null);
      ExceptionUtils.withCompilationHandler(
          reporter,
          () -> {
            box.set(makeCommand());
            reporter.failIfPendingErrors();
          });
      return box.get();
    }

    void error(Diagnostic diagnostic) {
      reporter.error(diagnostic);
      // For now all errors are fatal.
    }
  }

  Reporter getReporter() {
    return reporter;
  }

  List<ClassFileResourceProvider> getLibrary() {
    return library;
  }

  List<ClassFileResourceProvider> getTarget() {
    return traceTarget;
  }

  List<ProgramResourceProvider> getSource() {
    return traceSource;
  }

  TraceReferencesConsumer getConsumer() {
    return consumer;
  }

  InternalOptions getInternalOptions() {
    InternalOptions options = new InternalOptions();
    options.loadAllClassDefinitions = true;
    options.lookupLibraryBeforeProgram = true;
    TraceReferencesConsumer consumer = getConsumer();
    DumpOptions.Builder builder =
        DumpOptions.builder(Tool.TraceReferences)
            .readCurrentSystemProperties()
            // The behavior of TraceReferences greatly differs depending if we have a CheckConsumer
            // or a KeepRules consumer. We log the consumer type and obfuscation if relevant.
            .setTraceReferencesConsumer(consumer.getClass().getName());
    if (consumer instanceof TraceReferencesKeepRules) {
      builder.setMinification(((TraceReferencesKeepRules) consumer).allowObfuscation());
    }
    options.dumpOptions = builder.build();
    return options;
  }
}
