// 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.lib.cmdline;

import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;

import java.util.Collection;
import java.util.Set;

import javax.annotation.concurrent.Immutable;

/**
 * Contains the result of the target pattern evaluation. This is a specialized container class for
 * the result of target pattern resolution. There is no restriction on the element type, but it will
 * usually be {@code Target} or {@code Label}.
 */
@Immutable
public final class ResolvedTargets<T> {
  private static final ResolvedTargets<?> FAILED_RESULT =
      new ResolvedTargets<>(ImmutableSet.of(), ImmutableSet.of(), true);

  private static final ResolvedTargets<?> EMPTY_RESULT =
      new ResolvedTargets<>(ImmutableSet.of(), ImmutableSet.of(), false);

  @SuppressWarnings("unchecked")
  public static <T> ResolvedTargets<T> failed() {
    return (ResolvedTargets<T>) FAILED_RESULT;
  }

  @SuppressWarnings("unchecked")
  public static <T> ResolvedTargets<T> empty() {
    return (ResolvedTargets<T>) EMPTY_RESULT;
  }

  public static <T> ResolvedTargets<T> of(T target) {
    return new ResolvedTargets<>(ImmutableSet.<T>of(target), false);
  }

  private final boolean hasError;
  private final ImmutableSet<T> targets;
  private final ImmutableSet<T> filteredTargets;

  public ResolvedTargets(Set<T> targets, Set<T> filteredTargets, boolean hasError) {
    this.targets = ImmutableSet.copyOf(targets);
    this.filteredTargets = ImmutableSet.copyOf(filteredTargets);
    this.hasError = hasError;
  }

  public ResolvedTargets(Set<T> targets, boolean hasError) {
    this.targets = ImmutableSet.copyOf(targets);
    this.filteredTargets = ImmutableSet.of();
    this.hasError = hasError;
  }

  @Override
  public String toString() {
    return "ResolvedTargets(" + targets + ", filtered=" + filteredTargets
        + ", hasError=" + hasError + ")";
  }

  public boolean hasError() {
    return hasError;
  }

  public ImmutableSet<T> getTargets() {
    return targets;
  }

  public ImmutableSet<T> getFilteredTargets() {
    return filteredTargets;
  }

  /**
   * Returns a builder using concurrent sets, as long as you don't call filter.
   */
  public static <T> ResolvedTargets.Builder<T> concurrentBuilder() {
    return new ResolvedTargets.Builder<>(
        Sets.<T>newConcurrentHashSet(),
        Sets.<T>newConcurrentHashSet());
  }

  public static <T> ResolvedTargets.Builder<T> builder() {
    return new ResolvedTargets.Builder<>();
  }

  public static final class Builder<T> {
    private Set<T> targets;
    private Set<T> filteredTargets;
    private volatile boolean hasError = false;

    private Builder() {
      this(Sets.<T>newLinkedHashSet(), Sets.<T>newLinkedHashSet());
    }

    private Builder(Set<T> targets, Set<T> filteredTargets) {
      this.targets = targets;
      this.filteredTargets = filteredTargets;
    }

    public ResolvedTargets<T> build() {
      return new ResolvedTargets<>(targets, filteredTargets, hasError);
    }

    public Builder<T> merge(ResolvedTargets<T> other) {
      removeAll(other.filteredTargets);
      addAll(other.targets);
      if (other.hasError) {
        hasError = true;
      }
      return this;
    }

    public Builder<T> add(T target) {
      targets.add(target);
      filteredTargets.remove(target);
      return this;
    }

    public Builder<T> addAll(Collection<T> targets) {
      this.targets.addAll(targets);
      this.filteredTargets.removeAll(targets);
      return this;
    }

    public void remove(T target) {
      targets.remove(target);
      filteredTargets.add(target);
    }

    public Builder<T> removeAll(Collection<T> targets) {
      this.filteredTargets.addAll(targets);
      this.targets.removeAll(targets);
      return this;
    }

    public Builder<T> filter(Predicate<T> predicate) {
      Set<T> oldTargets = targets;
      targets = Sets.newLinkedHashSet();
      for (T target : oldTargets) {
        if (predicate.apply(target)) {
          add(target);
        } else {
          remove(target);
        }
      }
      return this;
    }

    public Builder<T> setError() {
      this.hasError = true;
      return this;
    }

    public Builder<T> mergeError(boolean hasError) {
      this.hasError |= hasError;
      return this;
    }

    public boolean isEmpty() {
      return targets.isEmpty();
    }
  }
}
