// Copyright 2016 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.collect.Iterables;
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import javax.annotation.Nullable;

/**
 * {@link NotifyingHelper} that returns reverse deps, temporary direct deps, and the results of
 * batch requests ordered alphabetically by sky key string representation.
 */
public class DeterministicHelper extends NotifyingHelper {
  public static final MemoizingEvaluator.GraphTransformerForTesting MAKE_DETERMINISTIC =
      makeTransformer(Listener.NULL_LISTENER, /*deterministic=*/ true);

  public static MemoizingEvaluator.GraphTransformerForTesting makeTransformer(
      final Listener listener, boolean deterministic) {
    if (deterministic) {
      return new MemoizingEvaluator.GraphTransformerForTesting() {
        @Override
        public InMemoryGraph transform(InMemoryGraph graph) {
          return new DeterministicInMemoryGraph(graph, listener);
        }

        @Override
        public QueryableGraph transform(QueryableGraph graph) {
          return new DeterministicQueryableGraph(graph, listener);
        }

        @Override
        public ProcessableGraph transform(ProcessableGraph graph) {
          return new DeterministicProcessableGraph(graph, listener);
        }
      };
    } else {
      return NotifyingHelper.makeNotifyingTransformer(listener);
    }
  }

  private static final Comparator<SkyKey> ALPHABETICAL_SKYKEY_COMPARATOR =
      new Comparator<SkyKey>() {
        @Override
        public int compare(SkyKey o1, SkyKey o2) {
          return o1.toString().compareTo(o2.toString());
        }
      };

  DeterministicHelper(Listener listener) {
    super(listener);
  }

  DeterministicHelper() {
    super(NotifyingHelper.Listener.NULL_LISTENER);
  }

  @Nullable
  @Override
  protected DeterministicValueEntry wrapEntry(SkyKey key, @Nullable ThinNodeEntry entry) {
    return entry == null ? null : new DeterministicValueEntry(key, entry);
  }

  private static Map<SkyKey, ? extends NodeEntry> makeDeterministic(
      Map<SkyKey, ? extends NodeEntry> map) {
    Map<SkyKey, NodeEntry> result = new TreeMap<>(ALPHABETICAL_SKYKEY_COMPARATOR);
    result.putAll(map);
    return result;
  }

  private static class DeterministicQueryableGraph extends NotifyingQueryableGraph {
    DeterministicQueryableGraph(QueryableGraph delegate, Listener graphListener) {
      super(delegate, new DeterministicHelper(graphListener));
    }

    @Override
    public Map<SkyKey, ? extends NodeEntry> getBatch(
        @Nullable SkyKey requestor, Reason reason, Iterable<? extends SkyKey> keys)
            throws InterruptedException {
      return makeDeterministic(super.getBatch(requestor, reason, keys));
    }
  }

  static class DeterministicProcessableGraph extends NotifyingProcessableGraph {
    DeterministicProcessableGraph(ProcessableGraph delegate, Listener graphListener) {
      super(delegate, new DeterministicHelper(graphListener));
    }

    DeterministicProcessableGraph(ProcessableGraph delegate) {
      this(delegate, Listener.NULL_LISTENER);
    }

    @Override
    public void remove(SkyKey key) {
      delegate.remove(key);
    }

    @Override
    public Map<SkyKey, ? extends NodeEntry> createIfAbsentBatch(
        @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys)
        throws InterruptedException {
      return makeDeterministic(super.createIfAbsentBatch(requestor, reason, keys));
    }

    @Override
    public Map<SkyKey, ? extends NodeEntry> getBatch(
        @Nullable SkyKey requestor, Reason reason, Iterable<? extends SkyKey> keys)
            throws InterruptedException {
      return makeDeterministic(super.getBatch(requestor, reason, keys));
    }
  }

  /**
   * This class uses TreeSet to store reverse dependencies of NodeEntry. As a result all values are
   * lexicographically sorted.
   */
  private class DeterministicValueEntry extends NotifyingNodeEntry {
    private DeterministicValueEntry(SkyKey myKey, ThinNodeEntry delegate) {
      super(myKey, delegate);
    }

    @Override
    public synchronized Collection<SkyKey> getReverseDepsForDoneEntry()
        throws InterruptedException {
      TreeSet<SkyKey> result = new TreeSet<>(ALPHABETICAL_SKYKEY_COMPARATOR);
      Iterables.addAll(result, super.getReverseDepsForDoneEntry());
      return result;
    }

    @Override
    public synchronized Set<SkyKey> getInProgressReverseDeps() {
      TreeSet<SkyKey> result = new TreeSet<>(ALPHABETICAL_SKYKEY_COMPARATOR);
      result.addAll(super.getInProgressReverseDeps());
      return result;
    }
  }
}
