// Copyright 2016 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 com.android.SdkConstants;
import com.android.resources.FolderTypeRelationship;
import com.android.resources.ResourceFolderType;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.devtools.build.android.AndroidResourceMerger.MergingException;
import com.google.devtools.build.android.FullyQualifiedName.Qualifiers;
import com.google.devtools.build.android.xml.StyleableXmlResourceValue;
import java.io.IOException;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable;
import javax.annotation.concurrent.NotThreadSafe;
import javax.xml.stream.XMLStreamException;

/**
 * Represents a collection of Android Resources.
 *
 * <p>The ParsedAndroidData is the primary building block for merging several AndroidDependencies
 * together. It extracts the android resource symbols (e.g. R.string.Foo) from the xml files to
 * allow an AndroidDataMerger to consume and produce a merged set of data.
 */
@Immutable
public class ParsedAndroidData {
  private static final Logger logger = Logger.getLogger(ParsedAndroidData.class.getCanonicalName());

  @NotThreadSafe
  static class Builder {
    private final Map<DataKey, DataResource> overwritingResources;
    private final Map<DataKey, DataResource> combiningResources;
    private final Map<DataKey, DataAsset> assets;
    private final Set<MergeConflict> conflicts;
    private final List<Exception> errors = new ArrayList<>();

    public Builder(
        Map<DataKey, DataResource> overwritingResources,
        Map<DataKey, DataResource> combiningResources,
        Map<DataKey, DataAsset> assets,
        Set<MergeConflict> conflicts) {
      this.overwritingResources = overwritingResources;
      this.combiningResources = combiningResources;
      this.assets = assets;
      this.conflicts = conflicts;
    }

    static Builder newBuilder() {
      final Map<DataKey, DataResource> overwritingResources = new LinkedHashMap<>();
      final Map<DataKey, DataResource> combiningResources = new LinkedHashMap<>();
      final Map<DataKey, DataAsset> assets = new LinkedHashMap<>();
      final Set<MergeConflict> conflicts = new LinkedHashSet<>();
      return new Builder(overwritingResources, combiningResources, assets, conflicts);
    }

    private void checkForErrors() throws MergingException {
      if (!errors.isEmpty()) {
        MergingException mergingException =
            MergingException.withMessage(String.format("%s Parse Error(s)", errors.size()));
        for (Exception e : errors) {
          mergingException.addSuppressed(e);
        }
        throw mergingException;
      }
    }

    ParsedAndroidData build() throws MergingException {
      checkForErrors();
      return ParsedAndroidData.of(
          ImmutableSet.copyOf(conflicts),
          ImmutableMap.copyOf(overwritingResources),
          ImmutableMap.copyOf(combiningResources),
          ImmutableMap.copyOf(assets));
    }

    /** Copies the data to the targetBuilder from the current builder. */
    public void copyTo(Builder targetBuilder) {
      KeyValueConsumers consumers = targetBuilder.consumers();
      for (Map.Entry<DataKey, DataResource> entry : overwritingResources.entrySet()) {
        consumers.overwritingConsumer.accept(entry.getKey(), entry.getValue());
      }
      for (Map.Entry<DataKey, DataResource> entry : combiningResources.entrySet()) {
        consumers.combiningConsumer.accept(entry.getKey(), entry.getValue());
      }
      for (Map.Entry<DataKey, DataAsset> entry : assets.entrySet()) {
        consumers.assetConsumer.accept(entry.getKey(), entry.getValue());
      }
      targetBuilder.conflicts.addAll(conflicts);
    }

    ResourceFileVisitor resourceVisitor() {
      return new ResourceFileVisitor(
          new OverwritableConsumer<>(overwritingResources, conflicts),
          new CombiningConsumer(combiningResources),
          errors);
    }

    AssetFileVisitor assetVisitorFor(Path path) {
      return new AssetFileVisitor(
          RelativeAssetPath.Factory.of(path), new OverwritableConsumer<>(assets, conflicts));
    }

    public KeyValueConsumers consumers() {
      return KeyValueConsumers.of(
          new OverwritableConsumer<>(overwritingResources, conflicts),
          new CombiningConsumer(combiningResources),
          new OverwritableConsumer<>(assets, conflicts));
    }
  }

  /** A Consumer style interface that will accept a DataKey and DataValue. */
  interface KeyValueConsumer<K extends DataKey, V extends DataValue> {
    void accept(K key, V value);
  }

  @VisibleForTesting
  static class CombiningConsumer implements KeyValueConsumer<DataKey, DataResource> {

    private Map<DataKey, DataResource> target;

    CombiningConsumer(Map<DataKey, DataResource> target) {
      this.target = target;
    }

    @Override
    public void accept(DataKey key, DataResource value) {
      if (target.containsKey(key)) {
        target.put(key, target.get(key).combineWith(value));
      } else {
        target.put(key, value);
      }
    }
  }

  @VisibleForTesting
  static class OverwritableConsumer<K extends DataKey, V extends DataValue>
      implements KeyValueConsumer<K, V> {
    private final Map<K, V> target;
    private final Set<MergeConflict> conflicts;
    private final boolean recordConflicts;

    OverwritableConsumer(Map<K, V> target, Set<MergeConflict> conflicts, boolean recordConflicts) {
      this.target = target;
      this.conflicts = conflicts;
      this.recordConflicts = recordConflicts;
    }

    OverwritableConsumer(Map<K, V> target, Set<MergeConflict> conflicts) {
      this(target, conflicts, true);
    }

    @Override
    public void accept(K key, V value) {
      if (target.containsKey(key)) {
        V other = target.get(key);
        if (other.source().hasOveridden(value.source())) {
          // technically a noop, but this complicated enough to explicit.
          target.put(key, other);
        } else if (value.source().hasOveridden(other.source())) {
          target.put(key, value);
        } else {
          target.put(
              key,
              value.compareMergePriorityTo(other) >= 0
                  ? overwrite(key, value, other)
                  : overwrite(key, other, value));
        }
      } else {
        target.put(key, value);
      }
    }

    private V overwrite(K key, V overwriter, V overwritee) {
      // TODO(corysmith): Cleanup type system.
      @SuppressWarnings("unchecked")
      V updated = (V) overwriter.update(overwriter.source().overwrite(overwritee.source()));
      if (recordConflicts) {
        conflicts.add(MergeConflict.between(key, updated, overwritee));
      }
      return updated;
    }
  }

  /** An AndroidDataPathWalker that collects DataAsset and DataResources for a ParsedAndroidData. */
  static final class ParsedAndroidDataBuildingPathWalker implements AndroidDataPathWalker {
    private static final ImmutableSet<FileVisitOption> FOLLOW_LINKS =
        ImmutableSet.of(FileVisitOption.FOLLOW_LINKS);
    private final Builder builder;

    private ParsedAndroidDataBuildingPathWalker(Builder builder) {
      this.builder = builder;
    }

    static ParsedAndroidDataBuildingPathWalker create(Builder builder) {
      return new ParsedAndroidDataBuildingPathWalker(builder);
    }

    @Override
    public void walkResources(Path path) throws IOException {
      Files.walkFileTree(path, FOLLOW_LINKS, Integer.MAX_VALUE, builder.resourceVisitor());
    }

    @Override
    public void walkAssets(Path path) throws IOException {
      Files.walkFileTree(path, FOLLOW_LINKS, Integer.MAX_VALUE, builder.assetVisitorFor(path));
    }

    ParsedAndroidData createParsedAndroidData() throws MergingException {
      return builder.build();
    }
  }

  /**
   * A {@link java.nio.file.FileVisitor} that walks the asset tree and extracts {@link DataAsset}s.
   */
  private static class AssetFileVisitor extends SimpleFileVisitor<Path> {
    private final RelativeAssetPath.Factory dataKeyFactory;
    private KeyValueConsumer<DataKey, DataAsset> assetConsumer;

    AssetFileVisitor(
        RelativeAssetPath.Factory dataKeyFactory,
        KeyValueConsumer<DataKey, DataAsset> assetConsumer) {
      this.dataKeyFactory = dataKeyFactory;
      this.assetConsumer = assetConsumer;
    }

    @Override
    public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
      if (!Files.isDirectory(path)) {
        RelativeAssetPath key = dataKeyFactory.create(path);
        DataValueFile asset = DataValueFile.of(path);
        assetConsumer.accept(key, asset);
      }
      return super.visitFile(path, attrs);
    }
  }

  /**
   * A FileVisitor that walks a resource tree and extract FullyQualifiedName and resource values.
   */
  private static class ResourceFileVisitor extends SimpleFileVisitor<Path> {
    private final KeyValueConsumer<DataKey, DataResource> overwritingConsumer;
    private final KeyValueConsumer<DataKey, DataResource> combiningResources;
    private final List<Exception> errors;
    private ResourceFolderType folderType;
    private FullyQualifiedName.Factory fqnFactory;

    /**
     * Resource folders with XML files that may contain "@+id". See android_ide_common's {@link
     * FolderTypeRelationship}.
     */
    private static final EnumSet<ResourceFolderType> ID_PROVIDING_RESOURCE_TYPES =
        EnumSet.of(
            ResourceFolderType.DRAWABLE,
            ResourceFolderType.LAYOUT,
            ResourceFolderType.MENU,
            ResourceFolderType.TRANSITION,
            ResourceFolderType.XML);

    ResourceFileVisitor(
        KeyValueConsumer<DataKey, DataResource> overwritingConsumer,
        KeyValueConsumer<DataKey, DataResource> combiningResources,
        List<Exception> errors) {
      this.overwritingConsumer = overwritingConsumer;
      this.combiningResources = combiningResources;
      this.errors = errors;
    }

    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
        throws IOException {
      try {
        final Qualifiers qualifiers = Qualifiers.parseFrom(dir.getFileName().toString());
        folderType = qualifiers.asFolderType();
        if (folderType == null) {
          return FileVisitResult.CONTINUE;
        }
        fqnFactory = FullyQualifiedName.Factory.using(qualifiers);
        return FileVisitResult.CONTINUE;
      } catch (IllegalArgumentException e) {
        logger.severe(
            String.format("%s is an invalid resource directory due to %s", dir, e.getMessage()));
        return FileVisitResult.SKIP_SUBTREE;
      }
    }

    @Override
    public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
      try {
        if (!Files.isDirectory(path) && !path.getFileName().toString().startsWith(".")) {
          if (folderType == ResourceFolderType.VALUES) {
            DataResourceXml.parse(
                XmlResourceValues.getXmlInputFactory(),
                path,
                fqnFactory,
                overwritingConsumer,
                combiningResources);
          } else if (folderType != null) {
            FullyQualifiedName key = fqnFactory.parse(path);
            if (ID_PROVIDING_RESOURCE_TYPES.contains(folderType)
                && path.getFileName().toString().endsWith(SdkConstants.DOT_XML)) {
              DataValueFileWithIds.parse(
                  XmlResourceValues.getXmlInputFactory(),
                  path,
                  key,
                  fqnFactory,
                  overwritingConsumer,
                  combiningResources);
            } else {
              overwritingConsumer.accept(key, DataValueFile.of(path));
            }
          }
        }
      } catch (IllegalArgumentException | XMLStreamException e) {
        errors.add(e);
      }
      return super.visitFile(path, attrs);
    }
  }

  /** Creates ParsedAndroidData of conflicts, assets overwriting and combining resources. */
  public static ParsedAndroidData of(
      ImmutableSet<MergeConflict> conflicts,
      ImmutableMap<DataKey, DataResource> overwritingResources,
      ImmutableMap<DataKey, DataResource> combiningResources,
      ImmutableMap<DataKey, DataAsset> assets) {
    return new ParsedAndroidData(conflicts, overwritingResources, combiningResources, assets);
  }

  /**
   * Creates an ParsedAndroidData from an UnvalidatedAndroidData.
   *
   * <p>The adding process parses out all the provided symbol into DataResources and DataAssets
   * objects.
   *
   * @param primary The primary data to parse into DataResources and DataAssets.
   * @throws IOException when there are issues with reading files.
   * @throws MergingException when there is invalid resource information.
   */
  public static ParsedAndroidData from(UnvalidatedAndroidDirectories primary)
      throws IOException, MergingException {
    final ParsedAndroidDataBuildingPathWalker pathWalker =
        ParsedAndroidDataBuildingPathWalker.create(Builder.newBuilder());
    primary.walk(pathWalker);
    return pathWalker.createParsedAndroidData();
  }

  /**
   * Creates an ParsedAndroidData from a list of DependencyAndroidData instances.
   *
   * <p>The adding process parses out all the provided symbol into DataResources and DataAssets
   * objects.
   *
   * @param dependencyAndroidDataList The dependency data to parse into DataResources and
   *     DataAssets.
   * @throws IOException when there are issues with reading files.
   * @throws MergingException when there is invalid resource information.
   */
  public static ParsedAndroidData from(List<DependencyAndroidData> dependencyAndroidDataList)
      throws IOException, MergingException {
    final ParsedAndroidDataBuildingPathWalker pathWalker =
        ParsedAndroidDataBuildingPathWalker.create(Builder.newBuilder());
    for (DependencyAndroidData data : dependencyAndroidDataList) {
      data.walk(pathWalker);
    }
    return pathWalker.createParsedAndroidData();
  }

  private static final class ParseDependencyDataTask implements Callable<Void> {

    private final DependencyInfo.DependencyType dependencyType;

    private final SerializedAndroidData dependency;

    private final Builder targetBuilder;

    private final AndroidDataDeserializer deserializer;

    private ParseDependencyDataTask(
        DependencyInfo.DependencyType dependencyType,
        AndroidDataDeserializer deserializer,
        SerializedAndroidData dependency,
        Builder targetBuilder) {
      this.dependencyType = dependencyType;
      this.deserializer = deserializer;
      this.dependency = dependency;
      this.targetBuilder = targetBuilder;
    }

    @Override
    public Void call() throws Exception {
      final Builder parsedDataBuilder = ParsedAndroidData.Builder.newBuilder();
      try {
        dependency.deserialize(dependencyType, deserializer, parsedDataBuilder.consumers());
      } catch (DeserializationException e) {
        if (!e.isLegacy()) {
          throw MergingException.wrapException(e);
        }
        logger.fine(
            String.format(
                "\u001B[31mDEPRECATION:\u001B[0m Legacy resources used for %s",
                dependency.getLabel()));
        // Legacy android resources -- treat them as direct dependencies.
        dependency.walk(ParsedAndroidDataBuildingPathWalker.create(parsedDataBuilder));
      }
      // The builder isn't threadsafe, so synchronize the copyTo call.
      synchronized (targetBuilder) {
        // All the resources are sorted before writing, so they can be aggregated in
        // whatever order here.
        parsedDataBuilder.copyTo(targetBuilder);
      }
      return null;
    }
  }

  /**
   * Deserializes data and merges them into a single {@link ParsedAndroidData}.
   *
   * @throws MergingException for deserialization errors.
   */
  public static ParsedAndroidData loadedFrom(
      DependencyInfo.DependencyType dependencyType,
      List<? extends SerializedAndroidData> data,
      ListeningExecutorService executorService,
      AndroidDataDeserializer deserializer) {
    List<ListenableFuture<Void>> tasks = new ArrayList<>();
    final Builder target = Builder.newBuilder();
    for (SerializedAndroidData serialized : data) {
      tasks.add(
          executorService.submit(
              new ParseDependencyDataTask(dependencyType, deserializer, serialized, target)));
    }
    FailedFutureAggregator.createForMergingExceptionWithMessage(
            "Failure(s) during dependency parsing")
        .aggregateAndMaybeThrow(tasks);
    return target.build();
  }

  private final ImmutableSet<MergeConflict> conflicts;
  private final ImmutableMap<DataKey, DataResource> overwritingResources;
  private final ImmutableMap<DataKey, DataResource> combiningResources;
  private final ImmutableMap<DataKey, DataAsset> assets;

  private ParsedAndroidData(
      ImmutableSet<MergeConflict> conflicts,
      ImmutableMap<DataKey, DataResource> overwritingResources,
      ImmutableMap<DataKey, DataResource> combiningResources,
      ImmutableMap<DataKey, DataAsset> assets) {
    this.conflicts = conflicts;
    this.overwritingResources = overwritingResources;
    this.combiningResources = combiningResources;
    this.assets = assets;
  }

  @Override
  public String toString() {
    return MoreObjects.toStringHelper(this)
        .add("overwritingResources", overwritingResources)
        .add("combiningResources", combiningResources)
        .add("assets", assets)
        .toString();
  }

  @Override
  public boolean equals(Object other) {
    if (this == other) {
      return true;
    }
    if (!(other instanceof ParsedAndroidData)) {
      return false;
    }
    ParsedAndroidData that = (ParsedAndroidData) other;
    return Objects.equals(overwritingResources, that.overwritingResources)
        && Objects.equals(combiningResources, that.combiningResources)
        && Objects.equals(conflicts, that.conflicts)
        && Objects.equals(assets, that.assets);
  }

  @Override
  public int hashCode() {
    return Objects.hash(conflicts, overwritingResources, combiningResources, assets);
  }

  /**
   * Returns a list of resources that would overwrite other values when defined.
   *
   * <p>Example:
   *
   * <p>A string resource (string.Foo=bar) could be redefined at string.Foo=baz.
   *
   * @return A map of key -&gt; overwriting resources.
   */
  @VisibleForTesting
  Map<DataKey, DataResource> getOverwritingResources() {
    return overwritingResources;
  }

  /**
   * Returns a list of resources are combined with other values that have the same key.
   *
   * <p>Example:
   *
   * <p>A id resource (id.Foo) combined id.Foo with no adverse effects, whereas two stylable.Bar
   * resources would be combined, resulting in a Styleable containing a union of the attributes. See
   * {@link StyleableXmlResourceValue} for more information.
   *
   * @return A map of key -&gt; combing resources.
   */
  @VisibleForTesting
  Map<DataKey, DataResource> getCombiningResources() {
    return combiningResources;
  }

  /**
   * Returns a list of assets.
   *
   * <p>Assets always overwrite during merging, just like overwriting resources.
   *
   * <p>Example:
   *
   * <p>A text asset (foo/bar.txt, containing fooza) could be replaced with (foo/bar.txt, containing
   * ouza!) depending on the merging process.
   *
   * @return A map of key -&gt; assets.
   */
  public Map<DataKey, DataAsset> getAssets() {
    return assets;
  }

  public boolean containsOverwritable(DataKey name) {
    return overwritingResources.containsKey(name);
  }

  public boolean containsCombineable(DataKey key) {
    return combiningResources.containsKey(key);
  }

  public DataResource getOverwritable(DataKey name) {
    return overwritingResources.get(name);
  }

  void writeResourcesTo(AndroidResourceSymbolSink writer) {
    for (Map.Entry<DataKey, DataResource> resource : iterateDataResourceEntries()) {
      resource.getValue().writeResourceToClass((FullyQualifiedName) resource.getKey(), writer);
    }
  }

  void writeResourcesTo(AndroidDataWriter writer) throws MergingException {
    for (Map.Entry<DataKey, DataResource> resource : iterateDataResourceEntries()) {
      resource.getValue().writeResource((FullyQualifiedName) resource.getKey(), writer);
    }
  }

  void serializeResourcesTo(AndroidDataSerializer serializer) {
    for (Map.Entry<DataKey, DataResource> resource : iterateDataResourceEntries()) {
      serializer.queueForSerialization(resource.getKey(), resource.getValue());
    }
  }

  void writeAssetsTo(AndroidDataWriter writer) throws IOException {
    for (Map.Entry<DataKey, DataAsset> resource : iterateAssetEntries()) {
      resource.getValue().writeAsset((RelativeAssetPath) resource.getKey(), writer);
    }
  }

  void serializeAssetsTo(AndroidDataSerializer serializer) {
    for (Map.Entry<DataKey, DataAsset> resource : iterateAssetEntries()) {
      serializer.queueForSerialization(resource.getKey(), resource.getValue());
    }
  }

  Iterable<Map.Entry<DataKey, DataResource>> iterateOverwritableEntries() {
    return overwritingResources.entrySet();
  }

  private Iterable<Map.Entry<DataKey, DataResource>> iterateDataResourceEntries() {
    return Iterables.concat(overwritingResources.entrySet(), combiningResources.entrySet());
  }

  public Iterable<Map.Entry<DataKey, DataResource>> iterateCombiningEntries() {
    return combiningResources.entrySet();
  }

  boolean containsAsset(DataKey name) {
    return assets.containsKey(name);
  }

  Iterable<Map.Entry<DataKey, DataAsset>> iterateAssetEntries() {
    return assets.entrySet();
  }

  MergeConflict foundResourceConflict(DataKey key, DataResource value) {
    return MergeConflict.between(key, overwritingResources.get(key), value);
  }

  MergeConflict foundAssetConflict(DataKey key, DataAsset value) {
    return MergeConflict.between(key, assets.get(key), value);
  }

  ImmutableSet<MergeConflict> conflicts() {
    return conflicts;
  }

  public DataAsset getAsset(DataKey key) {
    return assets.get(key);
  }
}
