// Copyright 2021 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.lib.cmdline;

import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import javax.annotation.Nullable;

/**
 * Stores the mapping from apparent repo name to canonical repo name, from the viewpoint of an
 * "owner repo".
 *
 * <p>For repositories from the WORKSPACE file, if the requested repo doesn't exist in the mapping,
 * we fallback to the requested name. For repositories from Bzlmod, we return null to let the caller
 * decide what to do.
 */
public class RepositoryMapping {
  /* A repo mapping that always falls back to using the apparent name as the canonical name. */
  public static final RepositoryMapping ALWAYS_FALLBACK = createAllowingFallback(ImmutableMap.of());

  private final ImmutableMap<String, RepositoryName> entries;
  @Nullable private final RepositoryName ownerRepo;

  private RepositoryMapping(
      Map<String, RepositoryName> entries, @Nullable RepositoryName ownerRepo) {
    this.entries = ImmutableMap.copyOf(entries);
    this.ownerRepo = ownerRepo;
  }

  /** Returns all the entries in this repo mapping. */
  public final ImmutableMap<String, RepositoryName> entries() {
    return entries;
  }

  /**
   * The owner repo of this repository mapping. It is for providing useful debug information when
   * repository mapping fails due to enforcing strict dependency, therefore it's only recorded when
   * we don't fall back to the requested repo name.
   */
  @Nullable
  public final RepositoryName ownerRepo() {
    return ownerRepo;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof RepositoryMapping)) {
      return false;
    }
    RepositoryMapping that = (RepositoryMapping) o;
    return Objects.equal(entries, that.entries) && Objects.equal(ownerRepo, that.ownerRepo);
  }

  @Override
  public int hashCode() {
    return Objects.hashCode(entries, ownerRepo);
  }

  @Override
  public String toString() {
    return String.format("RepositoryMapping{entries=%s, ownerRepo=%s}", entries, ownerRepo);
  }

  public static RepositoryMapping create(
      Map<String, RepositoryName> entries, RepositoryName ownerRepo) {
    return new RepositoryMapping(
        Preconditions.checkNotNull(entries), Preconditions.checkNotNull(ownerRepo));
  }

  public static RepositoryMapping createAllowingFallback(Map<String, RepositoryName> entries) {
    return new RepositoryMapping(Preconditions.checkNotNull(entries), null);
  }

  /**
   * Create a new {@link RepositoryMapping} instance based on existing repo mappings and given
   * additional mappings. If there are conflicts, existing mappings will take precedence.
   */
  public RepositoryMapping withAdditionalMappings(Map<String, RepositoryName> additionalMappings) {
    HashMap<String, RepositoryName> allMappings = new HashMap<>(additionalMappings);
    allMappings.putAll(entries());
    return new RepositoryMapping(allMappings, ownerRepo());
  }

  /**
   * Create a new {@link RepositoryMapping} instance based on existing repo mappings and given
   * additional mappings. If there are conflicts, existing mappings will take precedence. The owner
   * repo of the given additional mappings is ignored.
   */
  public RepositoryMapping withAdditionalMappings(RepositoryMapping additionalMappings) {
    return withAdditionalMappings(additionalMappings.entries());
  }

  /**
   * Returns the canonical repository name associated with the given apparent repo name. The
   * provided apparent repo name is assumed to be valid.
   */
  public RepositoryName get(String preMappingName) {
    RepositoryName canonicalRepoName = entries().get(preMappingName);
    if (canonicalRepoName != null) {
      return canonicalRepoName;
    }
    // If the owner repo is not present, that means we should fall back to the requested repo name.
    if (ownerRepo() == null) {
      return RepositoryName.createUnvalidated(preMappingName);
    } else {
      return RepositoryName.createUnvalidated(preMappingName).toNonVisible(ownerRepo());
    }
  }

  /**
   * Whether the repo with this mapping is subject to strict deps; when strict deps is off, unknown
   * apparent names are silently treated as canonical names.
   */
  public boolean usesStrictDeps() {
    return ownerRepo() != null;
  }

  /**
   * Returns the first apparent name in this mapping that maps to the given canonical name, if any.
   */
  public Optional<String> getInverse(RepositoryName postMappingName) {
    return entries().entrySet().stream()
        .filter(e -> e.getValue().equals(postMappingName))
        .map(Entry::getKey)
        .findFirst();
  }

  /**
   * Creates a new {@link RepositoryMapping} instance that is the equivalent of composing this
   * {@link RepositoryMapping} with another one. That is, {@code a.composeWith(b).get(name) ===
   * b.get(a.get(name))} (treating {@code b} as allowing fallback).
   *
   * <p>Since we're treating the result of {@code a.get(name)} as an apparent repo name instead of a
   * canonical repo name, this only really makes sense when {@code a} does not use strict deps (i.e.
   * allows fallback).
   */
  public RepositoryMapping composeWith(RepositoryMapping other) {
    Preconditions.checkArgument(
        !usesStrictDeps(), "only an allow-fallback mapping can be composed with other mappings");
    HashMap<String, RepositoryName> entries = new HashMap<>(other.entries());
    for (Map.Entry<String, RepositoryName> entry : entries().entrySet()) {
      RepositoryName mappedName = other.get(entry.getValue().getName());
      entries.put(entry.getKey(), mappedName.isVisible() ? mappedName : entry.getValue());
    }
    return new RepositoryMapping(entries, null);
  }

  /**
   * Returns a new {@link RepositoryMapping} instance with identical contents, except that the
   * inverse mapping is cached, causing {@link #getInverse} to be much more efficient. This is
   * particularly important for the main repo mapping, as it's often used to generate display-form
   * labels ({@link Label#getDisplayForm}).
   */
  public RepositoryMapping withCachedInverseMap() {
    var inverse = Maps.<RepositoryName, String>newHashMapWithExpectedSize(entries.size());
    for (Map.Entry<String, RepositoryName> entry : entries.entrySet()) {
      inverse.putIfAbsent(entry.getValue(), entry.getKey());
    }
    var inverseCopy = ImmutableMap.copyOf(inverse);
    return new RepositoryMapping(entries, ownerRepo) {
      @Override
      public Optional<String> getInverse(RepositoryName postMappingName) {
        return Optional.ofNullable(inverseCopy.get(postMappingName));
      }
    };
  }
}
