// Copyright 2017 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.android;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.android.builder.core.VariantType;
import com.android.manifmerger.ManifestMerger2;
import com.android.manifmerger.ManifestMerger2.Invoker;
import com.android.manifmerger.ManifestMerger2.Invoker.Feature;
import com.android.manifmerger.ManifestMerger2.MergeFailureException;
import com.android.manifmerger.ManifestMerger2.MergeType;
import com.android.manifmerger.ManifestMerger2.SystemProperty;
import com.android.manifmerger.MergingReport;
import com.android.manifmerger.MergingReport.MergedManifestKind;
import com.android.manifmerger.PlaceholderHandler;
import com.android.utils.Pair;
import com.android.utils.StdLogger;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

/** Provides manifest processing oriented tools. */
public class AndroidManifestProcessor {

  /** Wrapper exception for errors thrown during manifest processing. */
  public static class ManifestProcessingException extends RuntimeException {
    public ManifestProcessingException(Throwable e) {
      super(e);
    }

    public ManifestProcessingException(String message) {
      super(message);
    }
  }

  private static final ImmutableMap<SystemProperty, String> SYSTEM_PROPERTY_NAMES =
      Maps.toMap(
          Arrays.asList(SystemProperty.values()),
          property -> {
            if (property == SystemProperty.PACKAGE) {
              return "applicationId";
            } else {
              return property.toCamelCase();
            }
          });

  /** Creates a new processor with the appropriate logger. */
  public static AndroidManifestProcessor with(StdLogger stdLogger) {
    return new AndroidManifestProcessor(stdLogger);
  }

  private final StdLogger stdLogger;

  private AndroidManifestProcessor(StdLogger stdLogger) {
    this.stdLogger = stdLogger;
  }

  /**
   * Merge several manifests into one and perform placeholder substitutions. This operation uses
   * Gradle semantics.
   *
   * @param manifest The primary manifest of the merge.
   * @param mergeeManifests Manifests to be merged into {@code manifest}.
   * @param mergeType Whether the merger should operate in application or library mode.
   * @param values A map of strings to be used as manifest placeholders and overrides. packageName
   *     is the only disallowed value and will be ignored.
   * @param output The path to write the resultant manifest to.
   * @param logFile The path to write the merger log to.
   * @return The path of the resultant manifest, either {@code output}, or {@code manifest} if no
   *     merging was required.
   * @throws ManifestProcessingException if there was a problem writing the merged manifest.
   */
  // TODO(corysmith): Extract manifest processing.
  public Path mergeManifest(
      Path manifest,
      Map<Path, String> mergeeManifests,
      MergeType mergeType,
      Map<String, String> values,
      String customPackage,
      Path output,
      Path logFile,
      boolean logWarnings)
      throws ManifestProcessingException {
    if (mergeeManifests.isEmpty() && values.isEmpty() && Strings.isNullOrEmpty(customPackage)) {
      return manifest;
    }

    Invoker<?> manifestMerger = ManifestMerger2.newMerger(manifest.toFile(), stdLogger, mergeType);
    MergedManifestKind mergedManifestKind = MergedManifestKind.MERGED;
    if (mergeType == MergeType.APPLICATION) {
      manifestMerger.withFeatures(Feature.REMOVE_TOOLS_DECLARATIONS);
    }

    // Add mergee manifests
    List<Pair<String, File>> libraryManifests = new ArrayList<>();
    for (Map.Entry<Path, String> mergeeManifest : mergeeManifests.entrySet()) {
      libraryManifests.add(Pair.of(mergeeManifest.getValue(), mergeeManifest.getKey().toFile()));
    }
    manifestMerger.addLibraryManifests(libraryManifests);

    // Extract SystemProperties from the provided values.
    Map<String, Object> placeholders = new LinkedHashMap<>();
    placeholders.putAll(values);
    for (SystemProperty property : SystemProperty.values()) {
      if (values.containsKey(SYSTEM_PROPERTY_NAMES.get(property))) {
        manifestMerger.setOverride(property, values.get(SYSTEM_PROPERTY_NAMES.get(property)));

        // The manifest merger does not allow explicitly specifying either applicationId or
        // packageName as placeholders if SystemProperty.PACKAGE is specified. It forces these
        // placeholders to have the same value as specified by SystemProperty.PACKAGE.
        if (property == SystemProperty.PACKAGE) {
          placeholders.remove(PlaceholderHandler.APPLICATION_ID);
          placeholders.remove(PlaceholderHandler.PACKAGE_NAME);
        }
      }
    }

    // Add placeholders for all values.
    // packageName is populated from either the applicationId override or from the manifest itself;
    // it cannot be manually specified.
    placeholders.remove(PlaceholderHandler.PACKAGE_NAME);
    manifestMerger.setPlaceHolderValues(placeholders);

    // Ignore custom package at the binary level.
    if (!Strings.isNullOrEmpty(customPackage) && mergeType == MergeType.LIBRARY) {
      manifestMerger.setOverride(SystemProperty.PACKAGE, customPackage);
    }

    try {
      MergingReport mergingReport = manifestMerger.merge();

      if (logFile != null) {
        logFile.getParent().toFile().mkdirs();
        try (PrintStream stream = new PrintStream(logFile.toFile())) {
          mergingReport.log(new AndroidResourceProcessor.PrintStreamLogger(stream));
        }
      }
      switch (mergingReport.getResult()) {
        case WARNING:
          if (logWarnings) {
            mergingReport.log(stdLogger);
          }
          Files.createDirectories(output.getParent());
          writeMergedManifest(mergedManifestKind, mergingReport, output);
          break;
        case SUCCESS:
          Files.createDirectories(output.getParent());
          writeMergedManifest(mergedManifestKind, mergingReport, output);
          break;
        case ERROR:
          mergingReport.log(stdLogger);
          throw new ManifestProcessingException(mergingReport.getReportString());
        default:
          throw new ManifestProcessingException(
              "Unhandled result type : " + mergingReport.getResult());
      }
    } catch (MergeFailureException | IOException e) {
      throw new ManifestProcessingException(e);
    }

    return output;
  }

  /** Process a manifest for a library or a binary and return the merged android data. */
  public MergedAndroidData processManifest(
      VariantType variantType,
      String customPackageForR,
      String applicationId,
      int versionCode,
      String versionName,
      MergedAndroidData primaryData,
      Path processedManifest,
      boolean logWarnings) {

    ManifestMerger2.MergeType mergeType =
        variantType == VariantType.DEFAULT
            ? ManifestMerger2.MergeType.APPLICATION
            : ManifestMerger2.MergeType.LIBRARY;

    String newManifestPackage =
        variantType == VariantType.DEFAULT ? applicationId : customPackageForR;

    if (versionCode != -1 || versionName != null || newManifestPackage != null) {
      processManifest(
          versionCode,
          versionName,
          primaryData.getManifest(),
          processedManifest,
          mergeType,
          newManifestPackage,
          logWarnings);
      return new MergedAndroidData(
          primaryData.getResourceDir(), primaryData.getAssetDir(), processedManifest);
    }
    return primaryData;
  }

  /** Processes the manifest for a binary and return the manifest Path. */
  public Path processManifest(
      String applicationId,
      int versionCode,
      String versionName,
      Path manifest,
      Path processedManifest,
      boolean logWarnings) {

    if (versionCode != -1 || versionName != null || applicationId != null) {
      processManifest(
          versionCode,
          versionName,
          manifest,
          processedManifest,
          MergeType.APPLICATION,
          applicationId,
          logWarnings);
      return processedManifest;
    }
    return manifest;
  }

  /** Processes the manifest for a library and return the manifest Path. */
  public Path processLibraryManifest(
      String newManifestPackage, Path manifest, Path processedManifest, boolean logWarnings) {

    if (newManifestPackage != null) {
      processManifest(
          /* versionCode= */ -1,
          /* versionName= */ null,
          manifest,
          processedManifest,
          MergeType.LIBRARY,
          newManifestPackage,
          logWarnings);
      return processedManifest;
    }
    return manifest;
  }

  private void processManifest(
      int versionCode,
      String versionName,
      Path primaryManifest,
      Path processedManifest,
      MergeType mergeType,
      String newManifestPackage,
      boolean logWarnings) {
    try {
      Files.createDirectories(processedManifest.getParent());

      // The generics on Invoker don't make sense, so ignore them.
      @SuppressWarnings("unchecked")
      Invoker<?> manifestMergerInvoker =
          ManifestMerger2.newMerger(primaryManifest.toFile(), stdLogger, mergeType);
      // Stamp new package
      if (newManifestPackage != null) {
        manifestMergerInvoker.setOverride(SystemProperty.PACKAGE, newManifestPackage);
      }
      // Stamp version and applicationId (if provided) into the manifest
      if (versionCode > 0) {
        manifestMergerInvoker.setOverride(SystemProperty.VERSION_CODE, String.valueOf(versionCode));
      }
      if (versionName != null) {
        manifestMergerInvoker.setOverride(SystemProperty.VERSION_NAME, versionName);
      }

      MergedManifestKind mergedManifestKind = MergedManifestKind.MERGED;
      if (mergeType == MergeType.APPLICATION) {
        manifestMergerInvoker.withFeatures(Feature.REMOVE_TOOLS_DECLARATIONS);
      }

      MergingReport mergingReport = manifestMergerInvoker.merge();
      switch (mergingReport.getResult()) {
        case WARNING:
          if (logWarnings) {
            mergingReport.log(stdLogger);
          }
          writeMergedManifest(mergedManifestKind, mergingReport, processedManifest);
          break;
        case SUCCESS:
          writeMergedManifest(mergedManifestKind, mergingReport, processedManifest);
          break;
        case ERROR:
          mergingReport.log(stdLogger);
          throw new ManifestProcessingException(mergingReport.getReportString());
        default:
          throw new ManifestProcessingException(
              "Unhandled result type : " + mergingReport.getResult());
      }
    } catch (IOException | MergeFailureException e) {
      throw new ManifestProcessingException(e);
    }
  }

  /**
   * Overwrite the package attribute of {@code <manifest>} in an AndroidManifest.xml file.
   *
   * @param manifest The input manifest.
   * @param customPackage The package to write to the manifest.
   * @param output The output manifest to generate.
   * @return The output manifest if generated or the input manifest if no overwriting is required.
   */
  /* TODO(apell): switch from custom xml parsing to Gradle merger with NO_PLACEHOLDER_REPLACEMENT
   * set when android common is updated to version 2.5.0.
   */
  public Path writeManifestPackage(Path manifest, String customPackage, Path output) {
    if (Strings.isNullOrEmpty(customPackage)) {
      return manifest;
    }
    try {
      Files.createDirectories(output.getParent());
      XMLEventReader reader =
          XMLInputFactory.newInstance()
              .createXMLEventReader(Files.newInputStream(manifest), UTF_8.name());
      XMLEventWriter writer =
          XMLOutputFactory.newInstance()
              .createXMLEventWriter(Files.newOutputStream(output), UTF_8.name());
      XMLEventFactory eventFactory = XMLEventFactory.newInstance();
      while (reader.hasNext()) {
        XMLEvent event = reader.nextEvent();
        if (event.isStartElement()
            && event.asStartElement().getName().toString().equalsIgnoreCase("manifest")) {
          StartElement element = event.asStartElement();
          @SuppressWarnings("unchecked")
          Iterator<Attribute> attributes = element.getAttributes();
          ImmutableList.Builder<Attribute> newAttributes = ImmutableList.builder();
          while (attributes.hasNext()) {
            Attribute attr = attributes.next();
            if (attr.getName().toString().equalsIgnoreCase("package")) {
              newAttributes.add(eventFactory.createAttribute("package", customPackage));
            } else {
              newAttributes.add(attr);
            }
          }
          writer.add(
              eventFactory.createStartElement(
                  element.getName(), newAttributes.build().iterator(), element.getNamespaces()));
        } else {
          writer.add(event);
        }
      }
      writer.flush();
    } catch (XMLStreamException | FactoryConfigurationError | IOException e) {
      throw new ManifestProcessingException(e);
    }

    return output;
  }

  public void writeMergedManifest(
      MergedManifestKind mergedManifestKind, MergingReport mergingReport, Path manifestOut)
      throws ManifestProcessingException {
    String manifestContents = mergingReport.getMergedDocument(mergedManifestKind);
    String annotatedDocument = mergingReport.getMergedDocument(MergedManifestKind.BLAME);
    stdLogger.verbose(annotatedDocument);
    try {
      Files.write(manifestOut, manifestContents.getBytes(UTF_8));
    } catch (IOException e) {
      throw new ManifestProcessingException(e);
    }
  }
}
