// 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.analysis;

import static com.google.common.base.Preconditions.checkArgument;

import com.google.auto.value.AutoValue;
import com.google.common.base.MoreObjects;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Interner;
import com.google.devtools.build.lib.analysis.config.Fragment;
import com.google.devtools.build.lib.analysis.config.FragmentOptions;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.concurrent.BlazeInterners;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationConstant;
import com.google.devtools.build.lib.util.ClassName;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Provides a user-friendly list of the {@link Fragment}s and {@link
 * com.google.devtools.build.lib.analysis.config.FragmentOptions} required by this target and its
 * transitive dependencies.
 *
 * <p>See {@link com.google.devtools.build.lib.analysis.config.RequiredFragmentsUtil} for details.
 */
@AutoValue
@Immutable
public abstract class RequiredConfigFragmentsProvider implements TransitiveInfoProvider {

  private static final Interner<RequiredConfigFragmentsProvider> interner =
      BlazeInterners.newWeakInterner();

  @SerializationConstant
  public static final RequiredConfigFragmentsProvider EMPTY =
      new AutoValue_RequiredConfigFragmentsProvider(
          ImmutableSet.of(), ImmutableSet.of(), ImmutableSet.of(), ImmutableSet.of());

  RequiredConfigFragmentsProvider() {}

  public abstract ImmutableSet<Class<? extends FragmentOptions>> getOptionsClasses();

  public abstract ImmutableSet<Class<? extends Fragment>> getFragmentClasses();

  public abstract ImmutableSet<String> getDefines();

  public abstract ImmutableSet<Label> getStarlarkOptions();

  @Override
  public final String toString() {
    return MoreObjects.toStringHelper(RequiredConfigFragmentsProvider.class)
        .add(
            "optionsClasses",
            Collections2.transform(getOptionsClasses(), ClassName::getSimpleNameWithOuter))
        .add(
            "fragmentClasses",
            Collections2.transform(getFragmentClasses(), ClassName::getSimpleNameWithOuter))
        .add("defines", getDefines())
        .add("starlarkOptions", getStarlarkOptions())
        .toString();
  }

  /** Merges the values of one or more {@link RequiredConfigFragmentsProvider} instances. */
  public static RequiredConfigFragmentsProvider merge(
      List<RequiredConfigFragmentsProvider> providers) {
    checkArgument(!providers.isEmpty());
    RequiredConfigFragmentsProvider.Builder merged = null;
    RequiredConfigFragmentsProvider candidate = EMPTY;
    for (RequiredConfigFragmentsProvider provider : providers) {
      if (provider == EMPTY) {
        continue;
      }
      if (merged != null) {
        merged.merge(provider);
      } else if (candidate == EMPTY) {
        candidate = provider;
      } else {
        merged = builder().merge(candidate).merge(provider);
      }
    }
    return merged == null ? candidate : merged.build();
  }

  public static Builder builder() {
    return new Builder();
  }

  /**
   * Builder for required config fragments.
   *
   * <p>The builder uses a merging strategy that favors reuse of {@link ImmutableSet} instances and
   * avoids copying data if possible (i.e. when adding elements that are already present). For this
   * reason, adding transitively required fragments <em>before</em> directly required fragments is
   * likely to result in better performance, as it promotes reuse of existing sets from
   * dependencies.
   */
  public static final class Builder {
    private Set<Class<? extends FragmentOptions>> optionsClasses = ImmutableSet.of();
    private Set<Class<? extends Fragment>> fragmentClasses = ImmutableSet.of();
    private Set<String> defines = ImmutableSet.of();
    private Set<Label> starlarkOptions = ImmutableSet.of();

    private Builder() {}

    public Builder addOptionsClass(Class<? extends FragmentOptions> optionsClass) {
      optionsClasses = append(optionsClasses, optionsClass);
      return this;
    }

    public Builder addOptionsClasses(Collection<Class<? extends FragmentOptions>> optionsClasses) {
      this.optionsClasses = appendAll(this.optionsClasses, optionsClasses);
      return this;
    }

    public Builder addFragmentClasses(Collection<Class<? extends Fragment>> fragmentClasses) {
      this.fragmentClasses = appendAll(this.fragmentClasses, fragmentClasses);
      return this;
    }

    public Builder addDefine(String define) {
      defines = append(defines, define);
      return this;
    }

    public Builder addDefines(Collection<String> defines) {
      this.defines = appendAll(this.defines, defines);
      return this;
    }

    public Builder addStarlarkOption(Label starlarkOption) {
      starlarkOptions = append(starlarkOptions, starlarkOption);
      return this;
    }

    public Builder addStarlarkOptions(Collection<Label> starlarkOptions) {
      this.starlarkOptions = appendAll(this.starlarkOptions, starlarkOptions);
      return this;
    }

    public Builder merge(RequiredConfigFragmentsProvider provider) {
      optionsClasses = appendAll(optionsClasses, provider.getOptionsClasses());
      fragmentClasses = appendAll(fragmentClasses, provider.getFragmentClasses());
      defines = appendAll(defines, provider.getDefines());
      starlarkOptions = appendAll(starlarkOptions, provider.getStarlarkOptions());
      return this;
    }

    private static <T> Set<T> append(Set<T> set, T t) {
      if (set instanceof ImmutableSet) {
        if (set.contains(t)) {
          return set;
        }
        set = new HashSet<>(set);
      }
      set.add(t);
      return set;
    }

    private static <T> Set<T> appendAll(Set<T> set, Collection<T> ts) {
      if (ts instanceof Set) {
        return appendAll(set, (Set<T>) ts);
      }
      if (set instanceof ImmutableSet) {
        if (set.containsAll(ts)) {
          return set;
        }
        set = new HashSet<>(set);
      }
      set.addAll(ts);
      return set;
    }

    private static <T> Set<T> appendAll(Set<T> set, Set<T> ts) {
      if (set.size() > ts.size()) {
        if (set instanceof ImmutableSet && set.containsAll(ts)) {
          return set;
        }
      } else if (ts.size() > set.size()) {
        if (ts instanceof ImmutableSet && ts.containsAll(set)) {
          return ts;
        }
      } else { // Sizes equal.
        if (set instanceof ImmutableSet) {
          if (set.equals(ts)) {
            return set;
          }
        } else if (ts instanceof ImmutableSet && ts.equals(set)) {
          return ts;
        }
      }
      if (set instanceof ImmutableSet) {
        set = new HashSet<>(set);
      }
      set.addAll(ts);
      return set;
    }

    public RequiredConfigFragmentsProvider build() {
      if (optionsClasses.isEmpty()
          && fragmentClasses.isEmpty()
          && defines.isEmpty()
          && starlarkOptions.isEmpty()) {
        return EMPTY;
      }
      return interner.intern(
          new AutoValue_RequiredConfigFragmentsProvider(
              ImmutableSet.copyOf(optionsClasses),
              ImmutableSet.copyOf(fragmentClasses),
              ImmutableSet.copyOf(defines),
              ImmutableSet.copyOf(starlarkOptions)));
    }
  }
}
