// Copyright 2018 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.query2.testutil;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.eventbus.EventBus;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventCollector;
import com.google.devtools.build.lib.events.EventKind;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.query2.common.UniverseScope;
import com.google.devtools.build.lib.query2.engine.QueryEnvironment.Setting;
import com.google.devtools.build.lib.query2.testutil.AbstractQueryTest.QueryHelper;
import com.google.devtools.build.lib.testutil.MoreAsserts;
import java.util.Arrays;

/** Partial {@link QueryHelper} implementation for settings storage and event handling. */
public abstract class AbstractQueryHelper<T> implements QueryHelper<T> {
  private Reporter reporter;
  private EventCollector eventCollector;

  protected boolean keepGoing;
  protected ImmutableSet<Setting> settings = ImmutableSet.of();
  protected boolean orderedResults = true;
  protected UniverseScope universeScope = UniverseScope.EMPTY;

  @Override
  public void setUp() throws Exception {
    eventCollector = new EventCollector(EventKind.ERRORS_AND_WARNINGS);
    reporter = new Reporter(new EventBus(), eventCollector);
  }

  public Reporter getReporter() {
    return reporter;
  }

  @Override
  public void setUniverseScope(String universeScope) {
    this.universeScope =
        UniverseScope.fromUniverseScopeList(
            ImmutableList.copyOf(Arrays.asList(universeScope.split(","))));
  }

  @Override
  public void clearEvents() {
    eventCollector.clear();
  }

  @Override
  public void setOrderedResults(boolean orderedResults) {
    this.orderedResults = orderedResults;
  }

  @Override
  public void setKeepGoing(boolean keepGoing) {
    this.keepGoing = keepGoing;
  }

  @Override
  public boolean isKeepGoing() {
    return keepGoing;
  }

  @Override
  public void setQuerySettings(Setting... settings) {
    this.settings = ImmutableSet.copyOf(settings);
  }

  @Override
  public void assertContainsEvent(String expectedMessage) {
    MoreAsserts.assertContainsEvent(eventCollector, expectedMessage);
  }

  @Override
  public void assertDoesNotContainEvent(String expectedMessage) {
    MoreAsserts.assertDoesNotContainEvent(eventCollector, expectedMessage);
  }

  @Override
  public String getFirstEvent() {
    return eventCollector.iterator().next().getMessage();
  }

  @Override
  public Iterable<Event> getEvents() {
    return eventCollector;
  }
}
