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

import com.android.tools.r8.BaseCompilerCommandParser;
import com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.ClassFileConsumer.ArchiveConsumer;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.Diagnostic;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.Keep;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.references.PackageReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.shaking.ProguardConfiguration;
import com.android.tools.r8.shaking.ProguardPathList;
import com.android.tools.r8.utils.AbortException;
import com.android.tools.r8.utils.AndroidApp;
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.FlagFile;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.ThreadUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

@Keep
public class RelocatorCommand {

  private static final String THREAD_COUNT_FLAG = "--thread-count";

  private static final Set<String> OPTIONS_WITH_PARAMETER =
      ImmutableSet.of("--output", "--input", "--map", THREAD_COUNT_FLAG);

  static final String USAGE_MESSAGE =
      String.join(
          "\n",
          Iterables.concat(
              Arrays.asList(
                  "The Relocator CLI is EXPERIMENTAL and is subject to change",
                  "Usage: relocator [options]",
                  " where options are:",
                  "  --input <file>          # Input file to remap, class, zip or jar.",
                  "  --output <file>         # Output result in <outfile>.",
                  "  --map <from->to>        # Registers a mapping.",
                  "  --thread-count <number> # A specified number of threads to run with.",
                  "  --version               # Print the version of d8.",
                  "  --help                  # Print this message.")));

  private final boolean printHelp;
  private final boolean printVersion;
  private final Reporter reporter;
  private final DexItemFactory factory;
  private final ClassFileConsumer consumer;
  private final AndroidApp app;
  private final ImmutableMap<PackageReference, PackageReference> mapping;
  private final int threadCount;

  private RelocatorCommand(boolean printHelp, boolean printVersion) {
    this.printHelp = printHelp;
    this.printVersion = printVersion;
    reporter = null;
    factory = null;
    consumer = null;
    app = null;
    mapping = null;
    threadCount = ThreadUtils.NOT_SPECIFIED;
  }

  private RelocatorCommand(
      ImmutableMap<PackageReference, PackageReference> mapping,
      AndroidApp app,
      Reporter reporter,
      DexItemFactory factory,
      ClassFileConsumer consumer,
      int threadCount) {
    this.printHelp = false;
    this.printVersion = false;
    this.mapping = mapping;
    this.app = app;
    this.reporter = reporter;
    this.factory = factory;
    this.consumer = consumer;
    this.threadCount = threadCount;
  }

  public static Builder builder() {
    return new Builder();
  }

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

  public static Builder builder(DiagnosticsHandler diagnosticsHandler) {
    return new Builder(diagnosticsHandler);
  }

  public Reporter getReporter() {
    return reporter;
  }

  public DexItemFactory getFactory() {
    return factory;
  }

  public ClassFileConsumer getConsumer() {
    return consumer;
  }

  public int getThreadCount() {
    return threadCount;
  }

  public AndroidApp getApp() {
    return app;
  }

  public boolean isPrintHelp() {
    return printHelp;
  }

  public boolean isPrintVersion() {
    return printVersion;
  }

  public InternalOptions getInternalOptions() {
    // We are using the proguard configuration for adapting resources.
    InternalOptions options =
        new InternalOptions(
            // Set debug to ensure that we are writing all information to the application writer.
            CompilationMode.DEBUG,
            ProguardConfiguration.builder(factory, getReporter())
                .disableShrinking()
                .disableObfuscation()
                .disableOptimization()
                .addKeepAttributePatterns(ImmutableList.of("*"))
                .addAdaptResourceFilenames(ProguardPathList.builder().addFileName("**").build())
                .build(),
            getReporter());
    options.relocatorCompilation = true;
    options.threadCount = getThreadCount();
    options.programConsumer = consumer;
    assert consumer != null;
    options.dataResourceConsumer = consumer.getDataResourceConsumer();
    return options;
  }

  public Map<PackageReference, PackageReference> getMapping() {
    return mapping;
  }

  @Keep
  public static class Builder {

    private final AndroidApp.Builder app;
    private final Reporter reporter;
    private final ImmutableMap.Builder<PackageReference, PackageReference> mapping =
        ImmutableMap.builder();
    private ClassFileConsumer consumer = null;
    private int threadCount = ThreadUtils.NOT_SPECIFIED;
    private boolean printVersion;
    private boolean printHelp;

    Builder() {
      this(AndroidApp.builder());
    }

    Builder(DiagnosticsHandler handler) {
      this(AndroidApp.builder(new Reporter(handler)));
    }

    Builder(AndroidApp.Builder builder) {
      this.app = builder;
      this.reporter = builder.getReporter();
    }

    /**
     * Setting output to a path.
     *
     * <p>Setting the output path will override any previous set consumer or any previous set output
     * path.
     *
     * @param outputPath Output path to write output to. A null argument will clear the program
     *     consumer / output.
     */
    public Builder setOutputPath(Path outputPath) {
      if (outputPath == null) {
        this.consumer = null;
        return this;
      }
      this.consumer = new ArchiveConsumer(outputPath, true);
      return this;
    }

    public Builder setPrintHelp(boolean printHelp) {
      this.printHelp = printHelp;
      return this;
    }

    public Builder setPrintVersion(boolean printVersion) {
      this.printVersion = printVersion;
      return this;
    }

    /** Signal an error. */
    public void error(Diagnostic diagnostic) {
      reporter.error(diagnostic);
    }

    /** Set the number of threads to use for the compilation */
    public Builder setThreadCount(int threadCount) {
      if (threadCount <= 0) {
        reporter.error("Invalid threadCount: " + threadCount);
      } else {
        this.threadCount = threadCount;
      }
      return this;
    }

    /** Add program file resources. */
    public Builder addProgramFiles(Path... files) {
      return addProgramFiles(Arrays.asList(files));
    }

    /** Add program file resources. */
    public Builder addProgramFiles(Collection<Path> files) {
      guard(
          () -> {
            for (Path path : files) {
              try {
                app.addProgramFile(path);
              } catch (CompilationError e) {
                error(new PathOrigin(path), e);
              }
            }
          });
      return this;
    }

    /** Add program file resource. */
    public Builder addProgramFile(Path file) {
      guard(
          () -> {
            try {
              app.addProgramFile(file);
            } catch (CompilationError e) {
              error(new PathOrigin(file), e);
            }
          });
      return this;
    }

    public Builder addPackageMapping(PackageReference source, PackageReference destination) {
      mapping.put(source, destination);
      return this;
    }

    /**
     * Set the program consumer.
     *
     * <p>Setting the program consumer will override any previous set consumer or any previous set
     * output path.
     *
     * @param consumer ClassFile consumer to set as current. A null argument will clear the program
     *     consumer / output.
     */
    public Builder setConsumer(ClassFileConsumer consumer) {
      // Setting an explicit program consumer resets any output-path/mode setup.
      this.consumer = consumer;
      return this;
    }

    private void validate() {
      if (consumer == null) {
        reporter.error(new StringDiagnostic("No output path or consumer has been specified"));
      }
    }

    public RelocatorCommand build() throws CompilationFailedException {
      Box<RelocatorCommand> result = new Box<>();
      ExceptionUtils.withCompilationHandler(
          reporter,
          () -> {
            if (printHelp || printVersion) {
              result.set(new RelocatorCommand(printHelp, printVersion));
              return;
            }
            reporter.failIfPendingErrors();
            validate();
            reporter.failIfPendingErrors();
            DexItemFactory factory = new DexItemFactory();
            result.set(
                new RelocatorCommand(
                    mapping.build(), app.build(), reporter, factory, consumer, threadCount));
          });
      return result.get();
    }

    // Helper to signify an error.
    void error(Origin origin, Throwable throwable) {
      reporter.error(new ExceptionDiagnostic(throwable, origin));
    }

    // Helper to guard and handle exceptions.
    void guard(Runnable action) {
      try {
        action.run();
      } catch (CompilationError e) {
        reporter.error(e.toStringDiagnostic());
      } catch (AbortException e) {
        // Error was reported and exception will be thrown by build.
      }
    }

    /**
     * Parse the Relocator command-line.
     *
     * <p>Parsing will set the supplied options or their default value if they have any.
     *
     * @param args Command-line arguments array.
     * @param origin Origin description of the command-line arguments.
     * @return Relocator command builder with state set up according to parsed command line.
     */
    public static Builder parse(String[] args, Origin origin) {
      return parse(args, origin, RelocatorCommand.builder());
    }

    /**
     * Parse the Relocator command-line.
     *
     * <p>Parsing will set the supplied options or their default value if they have any.
     *
     * @param args Command-line arguments array.
     * @param origin Origin description of the command-line arguments.
     * @param handler Custom defined diagnostics handler.
     * @return Relocator command builder with state set up according to parsed command line.
     */
    public static Builder parse(String[] args, Origin origin, DiagnosticsHandler handler) {
      return parse(args, origin, RelocatorCommand.builder(handler));
    }

    private static Builder parse(String[] args, Origin origin, Builder builder) {
      String[] expandedArgs = FlagFile.expandFlagFiles(args, builder::error);
      Path outputPath = null;
      for (int i = 0; i < expandedArgs.length; i++) {
        String arg = expandedArgs[i].trim();
        String nextArg = null;
        if (OPTIONS_WITH_PARAMETER.contains(arg)) {
          if (++i < expandedArgs.length) {
            nextArg = expandedArgs[i];
          } else {
            builder.error(
                new StringDiagnostic("Missing parameter for " + expandedArgs[i - 1] + ".", origin));
            break;
          }
        }
        if (arg.length() == 0) {
          continue;
        }
        switch (arg) {
          case "--help":
            builder.setPrintHelp(true);
            break;
          case "--version":
            builder.setPrintVersion(true);
            break;
          case "--output":
            assert nextArg != null;
            if (outputPath != null) {
              builder.error(
                  new StringDiagnostic(
                      "Cannot output both to '" + outputPath.toString() + "' and '" + nextArg + "'",
                      origin));
              continue;
            }
            outputPath = Paths.get(nextArg);
            break;
          case "--input":
            assert nextArg != null;
            builder.addProgramFile(Paths.get(nextArg));
            break;
          case THREAD_COUNT_FLAG:
            BaseCompilerCommandParser.parsePositiveIntArgument(
                builder::error, arg, nextArg, origin, builder::setThreadCount);
            break;
          case "--map":
            assert nextArg != null;
            int separator = nextArg.indexOf("->");
            if (separator < 0) {
              builder.error(
                  new StringDiagnostic("--map " + nextArg + " is not on the form from->to"));
              continue;
            }
            // TODO(b/155047633): Handle invalid package names.
            builder.addPackageMapping(
                Reference.packageFromString(nextArg.substring(0, separator)),
                Reference.packageFromString(nextArg.substring(separator + 2)));
            break;
          default:
            builder.error(new StringDiagnostic("Unknown argument: " + arg, origin));
        }
      }
      if (outputPath == null) {
        outputPath = Paths.get(".");
      }
      builder.setOutputPath(outputPath);
      return builder;
    }
  }
}
