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

import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Interner;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;

/**
 * A saved {@link BzlLoadFunction} computation, used when inlining that Skyfunction.
 *
 * <p>This holds a requested key, its computed value, and the direct and transitive Skyframe
 * dependencies that are needed to compute it from scratch (i.e. if it weren't cached). Here
 * "transitive" means "underneath another {@code BzlLoadFunction} computation"; we split them into
 * other {@code CachedBzlLoadData} objects so they can be shared by other requesting bzls.
 */
class CachedBzlLoadData {
  private final BzlLoadValue.Key key;
  private final BzlLoadValue value;
  private final ImmutableList<Iterable<SkyKey>> directDeps;
  private final ImmutableList<CachedBzlLoadData> transitiveDeps;

  private CachedBzlLoadData(
      BzlLoadValue.Key key,
      BzlLoadValue value,
      ImmutableList<Iterable<SkyKey>> directDeps,
      ImmutableList<CachedBzlLoadData> transitiveDeps) {
    this.key = key;
    this.value = value;
    this.directDeps = directDeps;
    this.transitiveDeps = transitiveDeps;
  }

  /**
   * Adds all deps (direct and transitive) of this value to the {@code visitedDeps} set and passes
   * them to the consumer (with unspecified order and grouping). The traversal does not include
   * nodes already contained in {@code visitedDeps}.
   */
  void traverse(
      Consumer<Iterable<SkyKey>> depGroupConsumer,
      Map<BzlLoadValue.Key, CachedBzlLoadData> visitedDeps)
      throws InterruptedException {
    if (visitedDeps.putIfAbsent(key, this) != null) {
      return;
    }

    for (Iterable<SkyKey> directDepGroup : directDeps) {
      depGroupConsumer.accept(directDepGroup);
    }
    for (CachedBzlLoadData indirectDeps : transitiveDeps) {
      indirectDeps.traverse(depGroupConsumer, visitedDeps);
    }
  }

  BzlLoadValue getValue() {
    return value;
  }

  @Override
  public boolean equals(Object obj) {
    if (obj instanceof CachedBzlLoadData) {
      // With the interner, force there to be exactly one cached value per key at any given point
      // in time.
      return this.key.equals(((CachedBzlLoadData) obj).key);
    }
    return false;
  }

  @Override
  public int hashCode() {
    return key.hashCode();
  }

  static class Builder {
    Builder(Interner<CachedBzlLoadData> interner) {
      this.interner = interner;
    }

    private final Interner<CachedBzlLoadData> interner;
    private final List<Iterable<SkyKey>> directDeps = new ArrayList<>();
    private final List<CachedBzlLoadData> transitiveDeps = new ArrayList<>();
    private final AtomicReference<Exception> exceptionSeen = new AtomicReference<>(null);
    private BzlLoadValue value;
    private BzlLoadValue.Key key;

    @CanIgnoreReturnValue
    Builder addDep(SkyKey key) {
      directDeps.add(ImmutableList.of(key));
      return this;
    }

    @CanIgnoreReturnValue
    Builder addDeps(Iterable<SkyKey> keys) {
      directDeps.add(keys);
      return this;
    }

    @CanIgnoreReturnValue
    Builder noteException(Exception e) {
      exceptionSeen.set(e);
      return this;
    }

    @CanIgnoreReturnValue
    Builder addTransitiveDeps(CachedBzlLoadData transitiveDeps) {
      this.transitiveDeps.add(transitiveDeps);
      return this;
    }

    @CanIgnoreReturnValue
    Builder setValue(BzlLoadValue value) {
      this.value = value;
      return this;
    }

    @CanIgnoreReturnValue
    Builder setKey(BzlLoadValue.Key key) {
      this.key = key;
      return this;
    }

    CachedBzlLoadData build() {
      // We expect that we don't handle any exceptions in BzlLoadFunction directly.
      Preconditions.checkState(exceptionSeen.get() == null, "Caching a value in error?: %s", this);
      Preconditions.checkNotNull(value, "Expected value to be set: %s", this);
      Preconditions.checkNotNull(key, "Expected key to be set: %s", this);
      return interner.intern(
          new CachedBzlLoadData(
              key, value, ImmutableList.copyOf(directDeps), ImmutableList.copyOf(transitiveDeps)));
    }

    @Override
    public String toString() {
      return MoreObjects.toStringHelper(CachedBzlLoadData.Builder.class)
          .add("key", key)
          .add("value", value)
          .add("directDeps", directDeps)
          .add("transitiveDeps", transitiveDeps)
          .add("exceptionSeen", exceptionSeen)
          .toString();
    }

  }
}
