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

import static com.android.tools.r8.utils.DescriptorUtils.descriptorToInternalName;
import static com.android.tools.r8.utils.DescriptorUtils.descriptorToJavaType;
import static com.android.tools.r8.utils.DescriptorUtils.javaTypeToDescriptor;

import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.naming.MemberNaming.Signature;
import com.android.tools.r8.naming.mappinginformation.MapVersionMappingInformation;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableMap;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Mappings read from the given ProGuard map.
 * <p>
 * The main differences of this against {@link ClassNameMapper} and
 * {@link ClassNameMapper#getObfuscatedToOriginalMapping()} are:
 *   1) the key is the original descriptor, not the obfuscated java name. Thus, it is much easier
 *   to look up what mapping to apply while traversing {@link DexType}s; and
 *   2) the value is {@link ClassNamingForMapApplier}, another variant of {@link ClassNaming},
 *   which also uses original {@link Signature} as a key, instead of renamed {@link Signature}.
 */
public class SeedMapper implements ProguardMap {

  static class Builder extends ProguardMap.Builder {

    final Map<String, ClassNamingForMapApplier.Builder> map = new HashMap<>();
    final Set<String> mappedToDescriptorNames = new HashSet<>();
    private final Reporter reporter;

    private Builder(Reporter reporter) {
      this.reporter = reporter;
    }

    @Override
    ClassNamingForMapApplier.Builder classNamingBuilder(
        String renamedName, String originalName, Position position) {
      String originalDescriptor = javaTypeToDescriptor(originalName);
      String renamedDescriptorName = javaTypeToDescriptor(renamedName);
      mappedToDescriptorNames.add(renamedDescriptorName);
      ClassNamingForMapApplier.Builder classNamingBuilder =
          ClassNamingForMapApplier.builder(
              renamedDescriptorName, originalDescriptor, position, reporter);
      if (map.put(originalDescriptor, classNamingBuilder) != null) {
        reporter.error(ProguardMapError.duplicateSourceClass(originalName, position));
      }
      return classNamingBuilder;
    }

    @Override
    void addPreambleLine(String line) {
      // Do nothing.
    }

    @Override
    ProguardMap.Builder setCurrentMapVersion(MapVersionMappingInformation mapVersion) {
      // Do nothing
      return this;
    }

    @Override
    SeedMapper build() {
      reporter.failIfPendingErrors();
      return new SeedMapper(ImmutableMap.copyOf(map), mappedToDescriptorNames, reporter);
    }
  }

  static Builder builder(Reporter reporter) {
    return new Builder(reporter);
  }

  private static SeedMapper seedMapperFromInputStream(Reporter reporter, InputStream in)
      throws IOException {
    LineReader reader =
        LineReader.fromBufferedReader(
            new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)));
    try (ProguardMapReader proguardReader = new ProguardMapReader(reader, reporter, false, false)) {
      SeedMapper.Builder builder = SeedMapper.builder(reporter);
      proguardReader.parse(builder);
      return builder.build();
    }
  }

  public static SeedMapper seedMapperFromFile(Reporter reporter, Path path) throws IOException {
    return seedMapperFromInputStream(reporter, Files.newInputStream(path));
  }

  private final ImmutableMap<String, ClassNamingForMapApplier> mappings;
  private final Set<String> mappedToDescriptorNames;
  private final Reporter reporter;

  private SeedMapper(
      Map<String, ClassNamingForMapApplier.Builder> mappings,
      Set<String> mappedToDescriptorNames,
      Reporter reporter) {
    this.reporter = reporter;
    ImmutableMap.Builder<String, ClassNamingForMapApplier> builder = ImmutableMap.builder();
    for(Map.Entry<String, ClassNamingForMapApplier.Builder> entry : mappings.entrySet()) {
      builder.put(entry.getKey(), entry.getValue().build());
    }
    this.mappings = builder.build();
    this.mappedToDescriptorNames = mappedToDescriptorNames;
    verifyMappingsAreConflictFree();
  }

  private void verifyMappingsAreConflictFree() {
    Map<String, String> seenMappings = new HashMap<>();
    for (String key : mappings.keySet()) {
      ClassNamingForMapApplier classNaming = mappings.get(key);
      String existing = seenMappings.put(classNaming.renamedName, key);
      if (existing != null) {
        reporter.error(
            ProguardMapError.duplicateTargetClass(
                descriptorToJavaType(key),
                descriptorToJavaType(existing),
                descriptorToInternalName(classNaming.renamedName),
                classNaming.position));
      }
      // TODO(b/136694827) Enable when we have proper support
      // Map<Signature, MemberNaming> seenMembers = new HashMap<>();
      // classNaming.forAllMemberNaming(
      //     memberNaming -> {
      //       MemberNaming existingMember =
      //           seenMembers.put(memberNaming.renamedSignature, memberNaming);
      //       if (existingMember != null) {
      //         reporter.error(
      //             ProguardMapError.duplicateTargetSignature(
      //                 existingMember.signature,
      //                 memberNaming.signature,
      //                 memberNaming.getRenamedName(),
      //                 memberNaming.position));
      //       }
      //     });
    }
    reporter.failIfPendingErrors();
  }

  @Override
  public boolean hasMapping(DexType type) {
    return mappings.containsKey(type.descriptor.toString());
  }

  @Override
  public ClassNamingForMapApplier getClassNaming(DexType type) {
    return mappings.get(type.descriptor.toString());
  }

  public Set<String> getKeyset() {
    return mappings.keySet();
  }

  public Set<String> getMappedToDescriptorNames() {
    return mappedToDescriptorNames;
  }

  public ClassNamingForMapApplier getMapping(String key) {
    return mappings.get(key);
  }
}
