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

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.D8Command;
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.DexSplitterHelper;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.Keep;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.utils.AbortException;
import com.android.tools.r8.utils.DefaultDiagnosticsHandler;
import com.android.tools.r8.utils.ExceptionDiagnostic;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.FeatureClassMapping;
import com.android.tools.r8.utils.FeatureClassMapping.FeatureMappingException;
import com.android.tools.r8.utils.OptionsParsing;
import com.android.tools.r8.utils.OptionsParsing.ParseContext;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.ZipUtils;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

@Keep
public final class DexSplitter {

  private static final String DEFAULT_OUTPUT_DIR = "output";
  private static final String DEFAULT_BASE_NAME = "base";

  private static final boolean PRINT_ARGS = false;

  public static class FeatureJar {
    private String jar;
    private String outputName;

    public FeatureJar(String jar, String outputName) {
      this.jar = jar;
      this.outputName = outputName;
    }

    public FeatureJar(String jar) {
      this(jar, featureNameFromJar(jar));
    }

    public String getJar() {
      return jar;
    }

    public String getOutputName() {
      return outputName;
    }

    private static String featureNameFromJar(String jar) {
      Path jarPath = Paths.get(jar);
      String featureName = jarPath.getFileName().toString();
      if (featureName.endsWith(".jar") || featureName.endsWith(".zip")) {
        featureName = featureName.substring(0, featureName.length() - 4);
      }
      return featureName;
    }
  }

  private static class ZipFileOrigin extends PathOrigin {

    public ZipFileOrigin(Path path) {
      super(path);
    }

    @Override
    public String part() {
      return "splitting of file '" + super.part() + "'";
    }
  }

  @Keep
  public static final class Options {
    private final DiagnosticsHandler diagnosticsHandler = new DefaultDiagnosticsHandler();
    private List<String> inputArchives = new ArrayList<>();
    private List<FeatureJar> featureJars = new ArrayList<>();
    private String baseOutputName = DEFAULT_BASE_NAME;
    private String output = DEFAULT_OUTPUT_DIR;
    private String featureSplitMapping;
    private String proguardMap;
    private boolean splitNonClassResources = false;

    public DiagnosticsHandler getDiagnosticsHandler() {
      return diagnosticsHandler;
    }

    public String getOutput() {
      return output;
    }

    public void setOutput(String output) {
      this.output = output;
    }

    public String getFeatureSplitMapping() {
      return featureSplitMapping;
    }

    public void setFeatureSplitMapping(String featureSplitMapping) {
      this.featureSplitMapping = featureSplitMapping;
    }

    public String getProguardMap() {
      return proguardMap;
    }

    public void setProguardMap(String proguardMap) {
      this.proguardMap = proguardMap;
    }

    public String getBaseOutputName() {
      return baseOutputName;
    }

    public void setBaseOutputName(String baseOutputName) {
      this.baseOutputName = baseOutputName;
    }

    public void addInputArchive(String inputArchive) {
      inputArchives.add(inputArchive);
    }

    private void addFeatureJar(FeatureJar featureJar) {
      featureJars.add(featureJar);
    }

    public void addFeatureJar(String jar) {
      featureJars.add(new FeatureJar(jar));
    }

    public void addFeatureJar(String jar, String outputName) {
      featureJars.add(new FeatureJar(jar, outputName));
    }

    public void setSplitNonClassResources(boolean value) {
      splitNonClassResources = value;
    }

    public ImmutableList<String> getInputArchives() {
      return ImmutableList.copyOf(inputArchives);
    }

    ImmutableList<FeatureJar> getFeatureJars() {
      return ImmutableList.copyOf(featureJars);
    }

    // Shorthand error messages.
    public void error(String msg) {
      diagnosticsHandler.error(new StringDiagnostic(msg));
    }
  }

  /**
   * Parse a feature jar argument and return the corresponding FeatureJar representation.
   * Default to use the name of the jar file if the argument contains no ':', if the argument
   * contains ':', then use the value after the ':' as the name.
   * @param argument
   * @return
   */
  private static FeatureJar parseFeatureJarArgument(String argument) {
    if (argument.contains(":")) {
      String[] parts = argument.split(":");
      if (parts.length > 2) {
        throw new RuntimeException("--feature-jar argument contains more than one :");
      }
      return new FeatureJar(parts[0], parts[1]);
    }
    return new FeatureJar(argument);
  }

  private static Options parseArguments(String[] args) {
    Options options = new Options();
    ParseContext context = new ParseContext(args);
    while (context.head() != null) {
      List<String> inputs = OptionsParsing.tryParseMulti(context, "--input");
      if (inputs != null) {
        inputs.stream().forEach(options::addInputArchive);
        continue;
      }
      List<String> featureJars = OptionsParsing.tryParseMulti(context, "--feature-jar");
      if (featureJars != null) {
        featureJars.stream().forEach(
            (feature) -> options.addFeatureJar(parseFeatureJarArgument(feature)));
        continue;
      }
      String output = OptionsParsing.tryParseSingle(context, "--output", "-o");
      if (output != null) {
        options.setOutput(output);
        continue;
      }
      String proguardMap = OptionsParsing.tryParseSingle(context, "--proguard-map", null);
      if (proguardMap != null) {
        options.setProguardMap(proguardMap);
        continue;
      }
      String baseOutputName = OptionsParsing.tryParseSingle(context, "--base-output-name", null);
      if (baseOutputName != null) {
        options.setBaseOutputName(baseOutputName);
        continue;
      }
      String featureSplit = OptionsParsing.tryParseSingle(context, "--feature-splits", null);
      if (featureSplit != null) {
        options.setFeatureSplitMapping(featureSplit);
        continue;
      }
      Boolean b = OptionsParsing.tryParseBoolean(context, "--split-non-class-resources");
      if (b != null) {
        options.setSplitNonClassResources(b);
        continue;
      }
      throw new RuntimeException(String.format("Unknown options: '%s'.", context.head()));
    }
    return options;
  }

  private static FeatureClassMapping createFeatureClassMapping(Options options)
      throws FeatureMappingException {
    if (options.getFeatureSplitMapping() != null) {
      return FeatureClassMapping.fromSpecification(
          Paths.get(options.getFeatureSplitMapping()), options.getDiagnosticsHandler());
    }
    assert !options.getFeatureJars().isEmpty();
    return FeatureClassMapping.Internal.fromJarFiles(
        options.getFeatureJars(), options.getBaseOutputName(), options.getDiagnosticsHandler());
  }

  private static void run(String[] args)
      throws CompilationFailedException, FeatureMappingException {
    Options options = parseArguments(args);
    run(options);
  }

  public static void run(Options options)
      throws FeatureMappingException, CompilationFailedException {
    boolean errors = false;
    if (options.getInputArchives().isEmpty()) {
      errors = true;
      options.error("Need at least one --input");
    }
    if (options.getFeatureSplitMapping() == null && options.getFeatureJars().isEmpty()) {
      errors = true;
      options.error("You must supply a feature split mapping or feature jars");
    }
    if (options.getFeatureSplitMapping() != null && !options.getFeatureJars().isEmpty()) {
      errors = true;
      options.error("You can't supply both a feature split mapping and feature jars");
    }
    if (errors) {
      throw new AbortException();
    }

    D8Command.Builder builder = D8Command.builder();
    for (String s : options.inputArchives) {
      builder.addProgramFiles(Paths.get(s));
    }
    // We set the actual consumer on the ApplicationWriter when we have calculated the distribution
    // since we don't yet know the distribution.
    builder.setProgramConsumer(DexIndexedConsumer.emptyConsumer());

    FeatureClassMapping featureClassMapping = createFeatureClassMapping(options);

    DexSplitterHelper.run(
        builder.build(), featureClassMapping, options.getOutput(), options.getProguardMap());

    if (options.splitNonClassResources) {
      splitNonClassResources(options, featureClassMapping);
    }
  }

  private static void splitNonClassResources(Options options,
      FeatureClassMapping featureClassMapping) {
    for (String s : options.inputArchives) {
      try (ZipFile zipFile = new ZipFile(s, StandardCharsets.UTF_8)) {
        Enumeration<? extends ZipEntry> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
          ZipEntry entry = entries.nextElement();
          String name = entry.getName();
          if (!ZipUtils.isDexFile(name) && !ZipUtils.isClassFile(name)) {
            String feature = featureClassMapping.featureForNonClass(name);
            Path outputDir = Paths.get(options.getOutput()).resolve(feature);
            try (InputStream stream = zipFile.getInputStream(entry)) {
              Path outputFile = outputDir.resolve(name);
              Path parent = outputFile.getParent();
              if (parent != null) {
                Files.createDirectories(parent);
              }
              Files.copy(stream, outputFile);
            }
          }
        }
      } catch (IOException e) {
        options.getDiagnosticsHandler().error(
            new ExceptionDiagnostic(e, new ZipFileOrigin(Paths.get(s))));
        throw new AbortException();
      }
    }
  }

  public static void main(String[] args) {
    if (PRINT_ARGS) {
      printArgs(args);
    }
    ExceptionUtils.withMainProgramHandler(
        () -> {
          try {
            run(args);
          } catch (FeatureMappingException e) {
            // TODO(ricow): Report feature mapping errors via the reporter.
            System.err.println("Splitting failed: " + e.getMessage());
            System.exit(1);
          }
        });
  }

  private static void printArgs(String[] args) {
    System.err.printf("r8.DexSplitter");
    for (String s : args) {
      System.err.printf(" %s", s);
    }
    System.err.println("");
  }
}
