// Copyright 2014 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.skyframe;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.util.Preconditions;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * Data for a single cycle in the graph, together with the path to the cycle. For any value, the
 * head of path to the cycle should be the value itself, or, if the value is actually in the cycle,
 * the cycle should start with the value.
 */
public class CycleInfo {
  private final ImmutableList<SkyKey> cycle;
  private final ImmutableList<SkyKey> pathToCycle;

  @VisibleForTesting
  public CycleInfo(Iterable<SkyKey> cycle) {
    this(ImmutableList.<SkyKey>of(), cycle);
  }

  public CycleInfo(Iterable<SkyKey> pathToCycle, Iterable<SkyKey> cycle) {
    this.pathToCycle = ImmutableList.copyOf(pathToCycle);
    this.cycle = ImmutableList.copyOf(cycle);
  }

  // If a cycle is already known, but we are processing a value in the middle of the cycle, we need
  // to shift the cycle so that the value is at the head.
  private CycleInfo(Iterable<SkyKey> cycle, int cycleStart) {
    Preconditions.checkState(cycleStart >= 0, cycleStart);
    ImmutableList.Builder<SkyKey> cycleTail = ImmutableList.builder();
    ImmutableList.Builder<SkyKey> cycleHead = ImmutableList.builder();
    int index = 0;
    for (SkyKey key : cycle) {
      if (index >= cycleStart) {
        cycleHead.add(key);
      } else {
        cycleTail.add(key);
      }
      index++;
    }
    Preconditions.checkState(cycleStart < index, "%s >= %s ??", cycleStart, index);
    this.cycle = cycleHead.addAll(cycleTail.build()).build();
    this.pathToCycle = ImmutableList.of();
  }

  public ImmutableList<SkyKey> getCycle() {
    return cycle;
  }

  public ImmutableList<SkyKey> getPathToCycle() {
    return pathToCycle;
  }

  // Given a cycle and a value, if the value is part of the cycle, shift the cycle. Otherwise,
  // prepend the value to the head of pathToCycle.
  private static CycleInfo normalizeCycle(final SkyKey value, CycleInfo cycle) {
    int index = cycle.cycle.indexOf(value);
    if (index > -1) {
      if (!cycle.pathToCycle.isEmpty()) {
        // The head value we are considering is already part of a cycle, but we have reached it by a
        // roundabout way. Since we should have reached it directly as well, filter this roundabout
        // way out. Example (c has a dependence on top):
        //          top
        //         /  ^
        //        a   |
        //       / \ /
        //      b-> c
        // In the traversal, we start at top, visit a, then c, then top. This yields the
        // cycle {top,a,c}. Then we visit b, getting (b, {top,a,c}). Then we construct the full
        // error for a. The error should just be the cycle {top,a,c}, but we have an extra copy of
        // it via the path through b.
        return null;
      }
      return new CycleInfo(cycle.cycle, index);
    }
    return new CycleInfo(Iterables.concat(ImmutableList.of(value), cycle.pathToCycle),
        cycle.cycle);
  }

  /**
   * Normalize multiple cycles. This includes removing multiple paths to the same cycle, so that
   * a value does not depend on the same cycle multiple ways through the same child value. Note that
   * a value can still depend on the same cycle multiple ways, it's just that each way must be
   * through a different child value (a path with a different first element).
   */
  static Iterable<CycleInfo> prepareCycles(final SkyKey value, Iterable<CycleInfo> cycles) {
    final Set<ImmutableList<SkyKey>> alreadyDoneCycles = new HashSet<>();
    return Iterables.filter(Iterables.transform(cycles,
        new Function<CycleInfo, CycleInfo>() {
          @Override
          public CycleInfo apply(CycleInfo input) {
            CycleInfo normalized = normalizeCycle(value, input);
            if (normalized != null && alreadyDoneCycles.add(normalized.cycle)) {
              return normalized;
            }
            return null;
          }
    }), Predicates.notNull());
  }

  @Override
  public int hashCode() {
    return Objects.hash(cycle, pathToCycle);
  }

  @Override
  public boolean equals(Object that) {
    if (this == that) {
      return true;
    }
    if (!(that instanceof CycleInfo)) {
      return false;
    }

    CycleInfo thatCycle = (CycleInfo) that;
    return thatCycle.cycle.equals(this.cycle) && thatCycle.pathToCycle.equals(this.pathToCycle);
  }

  @Override
  public String toString() {
    return Iterables.toString(pathToCycle) + " -> " + Iterables.toString(cycle);
  }
}
