// 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 static com.google.common.truth.Truth.assertThat;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler.Postable;
import com.google.devtools.build.lib.skyframe.serialization.VisibleForSerialization;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
import com.google.devtools.build.skyframe.SkyKey.SkyKeyInterner;
import com.google.devtools.build.skyframe.SkyframeLookupResult.QueryDepCallback;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nullable;

/**
 * A helper class to create graphs and run skyframe tests over these graphs.
 *
 * <p>There are two types of values, computing values, which may not be set to a constant value,
 * and leaf values, which must be set to a constant value and may not have any dependencies.
 *
 * <p>Note that the value builder looks into the test values created here to determine how to
 * behave. However, skyframe will only re-evaluate the value and call the value builder if any of
 * its dependencies has changed. That means in order to change the set of dependencies of a value,
 * you need to also change one of its previous dependencies to force re-evaluation. Changing a
 * computing value does not mark it as modified.
 */
public class GraphTester {

  public static final SkyFunctionName NODE_TYPE = SkyFunctionName.FOR_TESTING;

  /** If true, uses the {@link SkyframeLookupResult#queryDep} interface to retrieve values. */
  private boolean useQueryDep = false;

  private final Map<SkyFunctionName, SkyFunction> functionMap = new HashMap<>();

  private final Map<SkyKey, TestFunction> values = new HashMap<>();
  private final Set<SkyKey> modifiedValues = new LinkedHashSet<>();

  public GraphTester() {
    functionMap.put(NODE_TYPE, new DelegatingFunction());
    functionMap.put(FOR_TESTING_NONHERMETIC, new DelegatingFunction());
  }

  public void setUseQueryDep(boolean useQueryDep) {
    this.useQueryDep = useQueryDep;
  }

  public TestFunction getOrCreate(String name) {
    return getOrCreate(skyKey(name));
  }

  public TestFunction getOrCreate(SkyKey key) {
    return getOrCreate(key, false);
  }

  public TestFunction getOrCreate(SkyKey key, boolean markAsModified) {
    TestFunction result = values.get(key);
    if (result == null) {
      result = new TestFunction();
      values.put(key, result);
    } else if (markAsModified) {
      modifiedValues.add(key);
    }
    return result;
  }

  public TestFunction set(String key, SkyValue value) {
    return set(skyKey(key), value);
  }

  public TestFunction set(SkyKey key, SkyValue value) {
    return getOrCreate(key, true).setConstantValue(value);
  }

  public ImmutableSet<SkyKey> getModifiedValues() {
    return ImmutableSet.copyOf(modifiedValues);
  }

  public void clearModifiedValues() {
    modifiedValues.clear();
  }

  public SkyFunction getFunction() {
    return new SkyFunction() {
      @Override
      public SkyValue compute(SkyKey key, Environment env)
          throws SkyFunctionException, InterruptedException {
        TestFunction builder = values.get(key);
        Preconditions.checkState(builder != null, "No TestFunction for " + key);
        if (builder.builder != null) {
          return builder.builder.compute(key, env);
        }
        if (builder.warning != null) {
          env.getListener().handle(Event.warn(builder.warning));
        }
        if (builder.progress != null) {
          env.getListener().handle(Event.progress(builder.progress));
        }
        if (builder.errorEvent != null) {
          env.getListener().handle(Event.error(builder.errorEvent));
        }
        if (builder.postable != null) {
          env.getListener().post(builder.postable);
        }
        Map<SkyKey, SkyValue> deps = new LinkedHashMap<>();
        boolean oneMissing = false;
        for (Pair<SkyKey, SkyValue> dep : builder.deps) {
          SkyValue value = useQueryDep ? getValueUsingQueryDep(dep, env) : getValue(dep, env);
          if (value == null) {
            oneMissing = true;
          } else {
            deps.put(dep.first, value);
          }
          Preconditions.checkState(
              oneMissing == env.valuesMissing(), "%s %s %s", dep, value, env.valuesMissing());
        }
        if (env.valuesMissing()) {
          return null;
        }

        if (builder.hasTransientError) {
          throw new GenericFunctionException(
              new SomeErrorException(key.toString()), Transience.TRANSIENT);
        }
        if (builder.hasError) {
          throw new GenericFunctionException(
              new SomeErrorException(key.toString()), Transience.PERSISTENT);
        }

        if (builder.value != null) {
          return builder.value;
        }

        if (Thread.currentThread().isInterrupted()) {
          throw new InterruptedException(key.toString());
        }

        return builder.computer.compute(deps, env);
      }

      @Nullable
      @Override
      public String extractTag(SkyKey skyKey) {
        TestFunction builder = values.get(skyKey);
        if (builder.builder != null) {
          return builder.builder.extractTag(skyKey);
        }
        return builder.tag;
      }
    };
  }

  private static SkyValue getValue(Pair<SkyKey, SkyValue> dep, SkyFunction.Environment env)
      throws InterruptedException {
    SkyValue value;
    if (dep.second == null) {
      value = env.getValue(dep.first);
    } else {
      try {
        value = env.getValueOrThrow(dep.first, SomeErrorException.class);
      } catch (SomeErrorException e) {
        value = dep.second;
      }
    }
    return value;
  }

  private static SkyValue getValueUsingQueryDep(
      Pair<SkyKey, SkyValue> dep, SkyFunction.Environment env) throws InterruptedException {
    SkyValue value;
    var lookupResult = env.getValuesAndExceptions(ImmutableList.of(dep.first));
    if (dep.second == null) {
      var valueRef = new AtomicReference<SkyValue>();
      var gotValue =
          lookupResult.queryDep(
              dep.first,
              (k, v) -> {
                assertThat(k).isEqualTo(dep.first);
                valueRef.set(v);
              });
      if ((value = valueRef.get()) != null) {
        assertThat(gotValue).isTrue();
      } else {
        assertThat(gotValue).isFalse();
      }
    } else {
      var valueRef = new AtomicReference<SkyValue>();
      var exceptionRef = new AtomicReference<SomeErrorException>();
      var gotValue =
          lookupResult.queryDep(
              dep.first,
              new QueryDepCallback() {
                @Override
                public void acceptValue(SkyKey key, SkyValue value) {
                  assertThat(key).isEqualTo(dep.first);
                  valueRef.set(value);
                }

                @Override
                public boolean tryHandleException(SkyKey key, Exception e) {
                  assertThat(key).isEqualTo(dep.first);
                  if (e instanceof SomeErrorException) {
                    exceptionRef.set((SomeErrorException) e);
                    return true;
                  }
                  return false;
                }
              });
      if ((value = valueRef.get()) != null) {
        assertThat(gotValue).isTrue();
      } else if (exceptionRef.get() != null) {
        value = dep.second;
        assertThat(gotValue).isTrue();
      } else {
        assertThat(gotValue).isFalse();
      }
    }
    return value;
  }

  public static SkyKey skyKey(String key) {
    return Key.create(key);
  }

  public static NonHermeticKey nonHermeticKey(String key) {
    return NonHermeticKey.create(key);
  }

  /** A value in the testing graph that is constructed in the tester. */
  public static class TestFunction {
    // TODO(bazel-team): We could use a multiset here to simulate multi-pass dependency discovery.
    private final Set<Pair<SkyKey, SkyValue>> deps = new LinkedHashSet<>();
    private SkyValue value;
    private ValueComputer computer;
    private SkyFunction builder = null;

    private boolean hasTransientError;
    private boolean hasError;

    private String warning;
    private String progress;
    private String errorEvent;
    private Postable postable;

    private String tag;

    @CanIgnoreReturnValue
    public TestFunction addDependency(String name) {
      return addDependency(skyKey(name));
    }

    @CanIgnoreReturnValue
    public TestFunction addDependency(SkyKey key) {
      deps.add(Pair.of(key, null));
      return this;
    }

    @CanIgnoreReturnValue
    public TestFunction removeDependency(String name) {
      return removeDependency(skyKey(name));
    }

    @CanIgnoreReturnValue
    public TestFunction removeDependency(SkyKey key) {
      deps.remove(Pair.<SkyKey, SkyValue>of(key, null));
      return this;
    }

    @CanIgnoreReturnValue
    public TestFunction addErrorDependency(SkyKey key, SkyValue altValue) {
      deps.add(Pair.of(key, altValue));
      return this;
    }

    @CanIgnoreReturnValue
    public TestFunction setConstantValue(SkyValue value) {
      Preconditions.checkState(this.computer == null);
      this.value = value;
      return this;
    }

    @CanIgnoreReturnValue
    public TestFunction unsetConstantValue() {
      this.value = null;
      return this;
    }

    @CanIgnoreReturnValue
    public TestFunction setComputedValue(ValueComputer computer) {
      Preconditions.checkState(this.value == null);
      this.computer = computer;
      return this;
    }

    @CanIgnoreReturnValue
    public TestFunction unsetComputedValue() {
      this.computer = null;
      return this;
    }

    @CanIgnoreReturnValue
    public TestFunction setBuilder(SkyFunction builder) {
      Preconditions.checkState(this.value == null);
      Preconditions.checkState(this.computer == null);
      Preconditions.checkState(deps.isEmpty());
      Preconditions.checkState(!hasTransientError);
      Preconditions.checkState(!hasError);
      Preconditions.checkState(warning == null);
      Preconditions.checkState(progress == null);
      Preconditions.checkState(errorEvent == null);
      Preconditions.checkState(tag == null);
      this.builder = builder;
      return this;
    }

    @CanIgnoreReturnValue
    public TestFunction setBuilderUnconditionally(SkyFunction builder) {
      this.builder = builder;
      return this;
    }

    @CanIgnoreReturnValue
    public TestFunction setHasTransientError(boolean hasError) {
      this.hasTransientError = hasError;
      return this;
    }

    @CanIgnoreReturnValue
    public TestFunction setHasError(boolean hasError) {
      // TODO(bazel-team): switch to an enum for hasError.
      this.hasError = hasError;
      return this;
    }

    @CanIgnoreReturnValue
    public TestFunction setWarning(String warning) {
      this.warning = warning;
      return this;
    }

    @CanIgnoreReturnValue
    public TestFunction setProgress(String info) {
      this.progress = info;
      return this;
    }

    /**
     * Sets an error message to emit as an {@link Event}. Does not imply that the function throws an
     * error.
     */
    @CanIgnoreReturnValue
    public TestFunction setErrorEvent(String error) {
      this.errorEvent = error;
      return this;
    }

    @CanIgnoreReturnValue
    public TestFunction setTag(String tag) {
      Preconditions.checkState(builder == null);
      this.tag = tag;
      return this;
    }

    @CanIgnoreReturnValue
    public TestFunction setPostable(Postable postable) {
      this.postable = postable;
      return this;
    }
  }

  public static ImmutableList<SkyKey> toSkyKeys(String... names) {
    ImmutableList.Builder<SkyKey> result = ImmutableList.builder();
    for (String element : names) {
      result.add(Key.create(element));
    }
    return result.build();
  }

  private class DelegatingFunction implements SkyFunction {
    @Override
    public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException,
        InterruptedException {
      return getFunction().compute(skyKey, env);
    }

    @Nullable
    @Override
    public String extractTag(SkyKey skyKey) {
      return getFunction().extractTag(skyKey);
    }
  }

  public ImmutableMap<SkyFunctionName, SkyFunction> getSkyFunctionMap() {
    return ImmutableMap.copyOf(functionMap);
  }

  public void putDelegateFunction(SkyFunctionName functionName) {
    putSkyFunction(functionName, new DelegatingFunction());
  }

  public void putSkyFunction(SkyFunctionName functionName, SkyFunction function) {
    functionMap.put(functionName, function);
  }

  /** Simple value class that stores strings. */
  public static class StringValue implements SkyValue {
    protected final String value;

    public StringValue(String value) {
      this.value = value;
    }

    public String getValue() {
      return value;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (!(o instanceof StringValue)) {
        return false;
      }
      return value.equals(((StringValue) o).value);
    }

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

    @Override
    public String toString() {
      return "StringValue: " + value;
    }

    public static StringValue of(String string) {
      return new StringValue(string);
    }

    public static StringValue from(SkyValue skyValue) {
      assertThat(skyValue).isInstanceOf(StringValue.class);
      return (StringValue) skyValue;
    }
  }

  /** A StringValue that is also a NotComparableSkyValue. */
  public static class NotComparableStringValue extends StringValue
          implements NotComparableSkyValue {
    public NotComparableStringValue(String value) {
      super(value);
    }

    @Override
    public boolean equals(Object o) {
      throw new UnsupportedOperationException(value + " is incomparable - what are you doing?");
    }

    @Override
    public int hashCode() {
      throw new UnsupportedOperationException(value + " is incomparable - what are you doing?");
    }
  }

  /**
   * A callback interface to provide the value computation.
   */
  public interface ValueComputer {
    /** This is called when all the declared dependencies exist. It may request new dependencies. */
    SkyValue compute(Map<SkyKey, SkyValue> deps, SkyFunction.Environment env)
        throws InterruptedException;
  }

  public static final ValueComputer COPY = (deps, env) -> Iterables.getOnlyElement(deps.values());

  public static final ValueComputer CONCATENATE =
      (deps, env) -> {
        StringBuilder result = new StringBuilder();
        for (SkyValue value : deps.values()) {
          result.append(((StringValue) value).value);
        }
        return new StringValue(result.toString());
      };

  public static ValueComputer formatter(SkyKey key, String format) {
    return (deps, env) ->
        StringValue.of(String.format(format, StringValue.from(deps.get(key)).getValue()));
  }

  @VisibleForSerialization
  @AutoCodec
  static class Key extends AbstractSkyKey<String> {
    private static final SkyKeyInterner<Key> interner = SkyKey.newInterner();

    private Key(String arg) {
      super(arg);
    }

    private static Key create(String arg) {
      return interner.intern(new Key(arg));
    }

    @VisibleForSerialization
    @AutoCodec.Interner
    static Key intern(Key key) {
      return interner.intern(key);
    }

    @Override
    public SkyFunctionName functionName() {
      return SkyFunctionName.FOR_TESTING;
    }

    @Override
    public SkyKeyInterner<Key> getSkyKeyInterner() {
      return interner;
    }
  }

  @VisibleForSerialization
  @AutoCodec
  static class NonHermeticKey extends AbstractSkyKey<String> {
    private static final SkyKeyInterner<NonHermeticKey> interner = SkyKey.newInterner();

    private NonHermeticKey(String arg) {
      super(arg);
    }

    private static NonHermeticKey create(String arg) {
      return interner.intern(new NonHermeticKey(arg));
    }

    @VisibleForSerialization
    @AutoCodec.Interner
    static NonHermeticKey intern(NonHermeticKey nonHermeticKey) {
      return interner.intern(nonHermeticKey);
    }

    @Override
    public SkyFunctionName functionName() {
      return FOR_TESTING_NONHERMETIC;
    }

    @Override
    public SkyKeyInterner<NonHermeticKey> getSkyKeyInterner() {
      return interner;
    }
  }

  private static final SkyFunctionName FOR_TESTING_NONHERMETIC =
      SkyFunctionName.createNonHermetic("FOR_TESTING_NONHERMETIC");
}
