// 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.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(
            ProguardConfiguration.builder(factory, getReporter())
                .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();
    // Set debug to ensure that we are writing all information to the application writer.
    options.debug = true;
    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;
    }
  }
}
