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

import com.android.tools.r8.DataDirectoryResource;
import com.android.tools.r8.DataEntryResource;
import com.android.tools.r8.DataResourceProvider;
import com.android.tools.r8.DataResourceProvider.Visitor;
import com.android.tools.r8.FeatureSplit;
import com.android.tools.r8.ProgramResourceProvider;
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.features.ClassToFeatureSplitMap;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.BiConsumer;

/** A description of the services and their implementations found in META-INF/services/. */
public class AppServices {

  public static final String SERVICE_DIRECTORY_NAME = "META-INF/services/";

  private final AppView<?> appView;

  // The graph lens that was previously used to rewrite this instance.
  private final GraphLens applied;

  // Mapping from service types to service implementation types.
  private final Map<DexType, Map<FeatureSplit, List<DexType>>> services;

  private AppServices(AppView<?> appView, Map<DexType, Map<FeatureSplit, List<DexType>>> services) {
    this.appView = appView;
    this.applied = appView.graphLens();
    this.services = services;
  }

  public boolean isEmpty() {
    return services.isEmpty();
  }

  public Set<DexType> allServiceTypes() {
    assert verifyRewrittenWithLens();
    return services.keySet();
  }

  public Set<DexType> computeAllServiceImplementations() {
    assert verifyRewrittenWithLens();
    Set<DexType> serviceImplementations = Sets.newIdentityHashSet();
    services.forEach(
        (serviceType, featureSplitListMap) ->
            featureSplitListMap.forEach(
                (feature, featureServiceImplementations) ->
                    serviceImplementations.addAll(featureServiceImplementations)));
    return serviceImplementations;
  }

  public List<DexType> serviceImplementationsFor(DexType serviceType) {
    assert verifyRewrittenWithLens();
    Map<FeatureSplit, List<DexType>> featureSplitListMap = services.get(serviceType);
    if (featureSplitListMap == null) {
      assert false
          : "Unexpected attempt to get service implementations for non-service type `"
              + serviceType.toSourceString()
              + "`";
      return ImmutableList.of();
    }
    ImmutableList.Builder<DexType> builder = ImmutableList.builder();
    for (List<DexType> implementations : featureSplitListMap.values()) {
      builder.addAll(implementations);
    }
    return builder.build();
  }

  public boolean hasServiceImplementationsInFeature(
      AppView<AppInfoWithLiveness> appView, DexType serviceType) {
    ClassToFeatureSplitMap classToFeatureSplitMap = appView.appInfo().getClassToFeatureSplitMap();
    if (classToFeatureSplitMap.isEmpty()) {
      return false;
    }
    Map<FeatureSplit, List<DexType>> featureImplementations = services.get(serviceType);
    if (featureImplementations == null || featureImplementations.isEmpty()) {
      assert false
          : "Unexpected attempt to get service implementations for non-service type `"
              + serviceType.toSourceString()
              + "`";
      return true;
    }
    if (featureImplementations.size() > 1
        || !featureImplementations.containsKey(FeatureSplit.BASE)) {
      return true;
    }
    // Check if service is defined feature
    DexProgramClass serviceClass = appView.definitionForProgramType(serviceType);
    if (serviceClass != null
        && classToFeatureSplitMap.isInFeature(serviceClass, appView.getSyntheticItems())) {
      return true;
    }
    for (DexType implementationType : featureImplementations.get(FeatureSplit.BASE)) {
      DexProgramClass implementationClass = appView.definitionForProgramType(implementationType);
      if (implementationClass != null
          && classToFeatureSplitMap.isInFeature(implementationClass, appView.getSyntheticItems())) {
        return true;
      }
    }
    return false;
  }

  public AppServices rewrittenWithLens(GraphLens graphLens) {
    ImmutableMap.Builder<DexType, Map<FeatureSplit, List<DexType>>> rewrittenFeatureMappings =
        ImmutableMap.builder();
    for (Entry<DexType, Map<FeatureSplit, List<DexType>>> entry : services.entrySet()) {
      DexType rewrittenServiceType = graphLens.lookupClassType(entry.getKey(), applied);
      ImmutableMap.Builder<FeatureSplit, List<DexType>> rewrittenFeatureImplementations =
          ImmutableMap.builder();
      for (Entry<FeatureSplit, List<DexType>> featureSplitImpls : entry.getValue().entrySet()) {
        ImmutableList.Builder<DexType> rewrittenServiceImplementationTypes =
            ImmutableList.builder();
        for (DexType serviceImplementationType : featureSplitImpls.getValue()) {
          rewrittenServiceImplementationTypes.add(
              graphLens.lookupClassType(serviceImplementationType, applied));
        }
        rewrittenFeatureImplementations.put(
            featureSplitImpls.getKey(), rewrittenServiceImplementationTypes.build());
      }
      rewrittenFeatureMappings.put(rewrittenServiceType, rewrittenFeatureImplementations.build());
    }
    return new AppServices(appView, rewrittenFeatureMappings.build());
  }

  public AppServices prunedCopy(PrunedItems prunedItems) {
    ImmutableMap.Builder<DexType, Map<FeatureSplit, List<DexType>>> rewrittenServicesBuilder =
        ImmutableMap.builder();
    for (Entry<DexType, Map<FeatureSplit, List<DexType>>> entry : services.entrySet()) {
      if (prunedItems.getRemovedClasses().contains(entry.getKey())) {
        continue;
      }
      ImmutableMap.Builder<FeatureSplit, List<DexType>> prunedFeatureSplitImpls =
          ImmutableMap.builder();
      for (Entry<FeatureSplit, List<DexType>> featureSplitEntry : entry.getValue().entrySet()) {
        ImmutableList.Builder<DexType> rewrittenServiceImplementationTypesBuilder =
            ImmutableList.builder();
        for (DexType serviceImplementationType : featureSplitEntry.getValue()) {
          if (!prunedItems.getRemovedClasses().contains(serviceImplementationType)) {
            rewrittenServiceImplementationTypesBuilder.add(serviceImplementationType);
          }
        }
        List<DexType> prunedFeatureSplitImplementations =
            rewrittenServiceImplementationTypesBuilder.build();
        if (prunedFeatureSplitImplementations.size() > 0) {
          prunedFeatureSplitImpls.put(
              featureSplitEntry.getKey(), rewrittenServiceImplementationTypesBuilder.build());
        }
      }
      ImmutableMap<FeatureSplit, List<DexType>> prunedServiceImplementations =
          prunedFeatureSplitImpls.build();
      if (prunedServiceImplementations.size() > 0) {
        rewrittenServicesBuilder.put(entry.getKey(), prunedServiceImplementations);
      }
    }
    return new AppServices(appView, rewrittenServicesBuilder.build());
  }

  public boolean verifyRewrittenWithLens() {
    for (Entry<DexType, Map<FeatureSplit, List<DexType>>> entry : services.entrySet()) {
      assert entry.getKey() == appView.graphLens().lookupClassType(entry.getKey(), applied);
      for (Entry<FeatureSplit, List<DexType>> featureEntry : entry.getValue().entrySet()) {
        for (DexType type : featureEntry.getValue()) {
          assert type == appView.graphLens().lookupClassType(type, applied);
        }
      }
    }
    return true;
  }

  public void visit(BiConsumer<DexType, List<DexType>> consumer) {
    services.forEach(
        (type, featureImpls) -> {
          ImmutableList.Builder<DexType> builder = ImmutableList.builder();
          featureImpls.values().forEach(builder::addAll);
          consumer.accept(type, builder.build());
        });
  }

  public static Builder builder(AppView<?> appView) {
    return new Builder(appView);
  }

  public static class Builder {

    private final AppView<?> appView;
    private final InternalOptions options;
    private final Map<DexType, Map<FeatureSplit, List<DexType>>> services = new LinkedHashMap<>();

    private Builder(AppView<?> appView) {
      this.appView = appView;
      this.options = appView.options();
    }

    public AppServices build() {
      for (DataResourceProvider provider : appView.appInfo().app().dataResourceProviders) {
        readServices(provider, FeatureSplit.BASE);
      }
      if (options.featureSplitConfiguration != null) {
        List<FeatureSplit> featureSplits = options.featureSplitConfiguration.getFeatureSplits();
        for (FeatureSplit featureSplit : featureSplits) {
          for (ProgramResourceProvider provider : featureSplit.getProgramResourceProviders()) {
            DataResourceProvider dataResourceProvider = provider.getDataResourceProvider();
            if (dataResourceProvider != null) {
              readServices(dataResourceProvider, featureSplit);
            }
          }
        }
      }
      return new AppServices(appView, services);
    }

    private void readServices(
        DataResourceProvider dataResourceProvider, FeatureSplit featureSplit) {
      try {
        dataResourceProvider.accept(new DataResourceProviderVisitor(featureSplit));
      } catch (ResourceException e) {
        throw new CompilationError(e.getMessage(), e);
      }
    }

    private class DataResourceProviderVisitor implements Visitor {

      private final FeatureSplit featureSplit;

      public DataResourceProviderVisitor(FeatureSplit featureSplit) {
        this.featureSplit = featureSplit;
      }

      @Override
      public void visit(DataDirectoryResource directory) {
        // Ignore.
      }

      @Override
      public void visit(DataEntryResource file) {
        try {
          String name = file.getName();
          if (!name.startsWith(SERVICE_DIRECTORY_NAME)) {
            return;
          }
          String serviceName = name.substring(SERVICE_DIRECTORY_NAME.length());
          if (!DescriptorUtils.isValidJavaType(serviceName)) {
            return;
          }
          String serviceDescriptor = DescriptorUtils.javaTypeToDescriptor(serviceName);
          DexType serviceType = appView.dexItemFactory().createType(serviceDescriptor);
          if (appView.enableWholeProgramOptimizations()) {
            DexClass serviceClass =
                appView.appInfo().definitionForWithoutExistenceAssert(serviceType);
            if (serviceClass == null) {
              warn(
                  "Unexpected reference to missing service class: META-INF/services/"
                      + serviceType.toSourceString()
                      + ".",
                  serviceType,
                  file.getOrigin());
            }
          }
          byte[] bytes = ByteStreams.toByteArray(file.getByteStream());
          String contents = new String(bytes, Charset.defaultCharset());
          Map<FeatureSplit, List<DexType>> featureSplitImplementations =
              services.computeIfAbsent(serviceType, k -> new LinkedHashMap<>());
          List<DexType> serviceImplementations =
              featureSplitImplementations.computeIfAbsent(featureSplit, f -> new ArrayList<>());
          readServiceImplementationsForService(
              contents, file.getOrigin(), serviceType, serviceImplementations);
        } catch (IOException | ResourceException e) {
          throw new CompilationError(e.getMessage(), e);
        }
      }

      private void readServiceImplementationsForService(
          String contents,
          Origin origin,
          DexType serviceType,
          List<DexType> serviceImplementations) {
        if (contents != null) {
          StringUtils.splitLines(contents).stream()
              .map(String::trim)
              .map(this::prefixUntilCommentChar)
              .filter(line -> !line.isEmpty())
              .filter(DescriptorUtils::isValidJavaType)
              .map(DescriptorUtils::javaTypeToDescriptor)
              .map(appView.dexItemFactory()::createType)
              .filter(
                  serviceImplementationType -> {
                    if (!serviceImplementationType.isClassType()) {
                      // Should never happen.
                      warn(
                          "Unexpected service implementation found in META-INF/services/"
                              + serviceType.toSourceString()
                              + ": "
                              + serviceImplementationType.toSourceString()
                              + ".",
                          serviceImplementationType,
                          origin);
                      return false;
                    }
                    if (appView.enableWholeProgramOptimizations()) {
                      DexClass serviceImplementationClass =
                          appView
                              .appInfo()
                              .definitionForWithoutExistenceAssert(serviceImplementationType);
                      if (serviceImplementationClass == null) {
                        warn(
                            "Unexpected reference to missing service implementation class in "
                                + "META-INF/services/"
                                + serviceType.toSourceString()
                                + ": "
                                + serviceImplementationType.toSourceString()
                                + ".",
                            serviceImplementationType,
                            origin);
                      }
                    }
                    // Only keep one of each implementation type in the list.
                    return !serviceImplementations.contains(serviceImplementationType);
                  })
              .forEach(serviceImplementations::add);
        }
      }

      private String prefixUntilCommentChar(String line) {
        int commentCharIndex = line.indexOf('#');
        return commentCharIndex > -1 ? line.substring(0, commentCharIndex) : line;
      }

      private void warn(String message, DexType type, Origin origin) {
        if (!appView.getDontWarnConfiguration().matches(type)) {
          options.reporter.warning(new StringDiagnostic(message, origin));
        }
      }
    }
  }
}
