// 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.desugar.graph;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.DesugarGraphConsumer;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.StringUtils.BraceType;
import com.android.tools.r8.utils.WorkList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

public class DesugarGraphTestConsumer implements DesugarGraphConsumer {

  private boolean finished = false;

  // Map from a dependency to its immediate dependents.
  private final Map<Origin, Set<Origin>> dependents = new HashMap<>();

  // Map from a dependent to its immedate dependencies.
  private Map<Origin, Set<Origin>> dependencies = null;

  @Override
  public String toString() {
    if (dependents.isEmpty()) {
      return "<empty>";
    }
    StringBuilder builder = new StringBuilder();
    dependents.forEach(
        (k, vs) ->
            StringUtils.append(builder.append(k).append(" -> "), vs, ", ", BraceType.TUBORG)
                .append("\n"));
    return builder.toString();
  }

  public Set<Origin> getDirectDependencies(Origin dependent) {
    return Collections.unmodifiableSet(
        dependencies.getOrDefault(dependent, Collections.emptySet()));
  }

  public Set<Origin> getDirectDependents(Origin dependency) {
    return Collections.unmodifiableSet(dependents.getOrDefault(dependency, Collections.emptySet()));
  }

  public Set<Origin> getTransitiveDependencies(Origin dependent) {
    return getTransitiveClosure(dependent, this::getDirectDependencies);
  }

  public Set<Origin> getTransitiveDependents(Origin dependency) {
    return getTransitiveClosure(dependency, this::getDirectDependents);
  }

  private static Set<Origin> getTransitiveClosure(
      Origin item, Function<Origin, Set<Origin>> edges) {
    WorkList<Origin> worklist = WorkList.newEqualityWorkList(edges.apply(item));
    while (worklist.hasNext()) {
      worklist.addIfNotSeen(edges.apply(worklist.next()));
    }
    return worklist.getSeenSet();
  }

  public boolean contains(Origin dependency, Origin dependent) {
    assertTrue(finished);
    return dependents.getOrDefault(dependency, Collections.emptySet()).contains(dependent);
  }

  public int totalEdgeCount() {
    assertTrue(finished);
    int count = 0;
    for (Set<Origin> dependents : dependents.values()) {
      count += dependents.size();
    }
    return count;
  }

  @Override
  public synchronized void accept(Origin dependent, Origin dependency) {
    assertFalse(finished);
    dependents.computeIfAbsent(dependency, s -> new HashSet<>()).add(dependent);
  }

  @Override
  public void finished() {
    assertFalse(finished);
    finished = true;
    dependencies = new HashMap<>();
    dependents.forEach(
        (dependency, dependents) ->
            dependents.forEach(
                dependent ->
                    dependencies.computeIfAbsent(dependent, k -> new HashSet<>()).add(dependency)));
  }
}
