// 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.VariantTypeImpl;
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.ManifestSystemProperty;
import com.android.manifmerger.MergingReport;
import com.android.manifmerger.MergingReport.MergedManifestKind;
import com.android.manifmerger.PlaceholderHandler;
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.IOException;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
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<ManifestSystemProperty, String> SYSTEM_PROPERTY_NAMES =
      Maps.toMap(
          Arrays.asList(ManifestSystemProperty.values()),
          property -> {
            if (property == ManifestSystemProperty.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);
    manifestMerger.withFeatures(Feature.HANDLE_VALUE_CONFLICTS_AUTOMATICALLY);
    MergedManifestKind mergedManifestKind = MergedManifestKind.MERGED;
    if (mergeType == MergeType.APPLICATION) {
      manifestMerger.withFeatures(Feature.REMOVE_TOOLS_DECLARATIONS);
    }

    // Add mergee manifests
    for (Map.Entry<Path, String> mergeeManifest : mergeeManifests.entrySet()) {
      manifestMerger.addLibraryManifest(
          mergeeManifest.getValue(), mergeeManifest.getKey().toFile());
    }

    // Extract SystemProperties from the provided values.
    Map<String, Object> placeholders = new LinkedHashMap<>();
    placeholders.putAll(values);
    for (ManifestSystemProperty property : ManifestSystemProperty.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 ManifestSystemProperty.PACKAGE is specified. It forces
        // these placeholders to have the same value as specified by ManifestSystemProperty.PACKAGE.
        if (property == ManifestSystemProperty.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(ManifestSystemProperty.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(
      VariantTypeImpl variantType,
      String customPackageForR,
      String applicationId,
      int versionCode,
      String versionName,
      MergedAndroidData primaryData,
      Path processedManifest,
      boolean logWarnings) {

    ManifestMerger2.MergeType mergeType =
        variantType == VariantTypeImpl.BASE_APK
            ? ManifestMerger2.MergeType.APPLICATION
            : ManifestMerger2.MergeType.LIBRARY;

    String newManifestPackage =
        variantType == VariantTypeImpl.BASE_APK ? 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;
  }

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

      Invoker manifestMergerInvoker =
          ManifestMerger2.newMerger(primaryManifest.toFile(), stdLogger, mergeType);
      // Stamp new package
      if (newManifestPackage != null) {
        manifestMergerInvoker.setOverride(ManifestSystemProperty.PACKAGE, newManifestPackage);
      }
      // Stamp version and applicationId (if provided) into the manifest
      if (versionCode > 0) {
        manifestMergerInvoker.setOverride(
            ManifestSystemProperty.VERSION_CODE, String.valueOf(versionCode));
      }
      if (versionName != null) {
        manifestMergerInvoker.setOverride(ManifestSystemProperty.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);
    }
  }

  /** 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;
  }

  /**
   * 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();
          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);
    }
  }
}
