// 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.common.base.MoreObjects;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.devtools.build.lib.analysis.config.Fragment;
import com.google.devtools.build.lib.analysis.config.FragmentClassSet;
import com.google.devtools.build.lib.analysis.config.FragmentOptions;
import com.google.devtools.build.lib.cmdline.Label;
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.List;

/**
 * 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.
 */
@Immutable
public final class RequiredConfigFragmentsProvider implements TransitiveInfoProvider {

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

  private final ImmutableSet<Class<? extends FragmentOptions>> optionsClasses;
  private final FragmentClassSet fragmentClasses;
  private final ImmutableSet<String> defines;
  private final ImmutableSet<Label> starlarkOptions;

  private RequiredConfigFragmentsProvider(
      ImmutableSet<Class<? extends FragmentOptions>> optionsClasses,
      FragmentClassSet fragmentClasses,
      ImmutableSet<String> defines,
      ImmutableSet<Label> starlarkOptions) {
    this.optionsClasses = optionsClasses;
    this.fragmentClasses = fragmentClasses;
    this.defines = defines;
    this.starlarkOptions = starlarkOptions;
  }

  public ImmutableSet<Class<? extends FragmentOptions>> getOptionsClasses() {
    return optionsClasses;
  }

  public FragmentClassSet getFragmentClasses() {
    return fragmentClasses;
  }

  public ImmutableSet<String> getDefines() {
    return defines;
  }

  public ImmutableSet<Label> getStarlarkOptions() {
    return starlarkOptions;
  }

  @Override
  public String toString() {
    return MoreObjects.toStringHelper(this)
        .add(
            "optionsClasses",
            Collections2.transform(optionsClasses, ClassName::getSimpleNameWithOuter))
        .add("fragmentClasses", fragmentClasses)
        .add("defines", defines)
        .add("starlarkOptions", starlarkOptions)
        .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. */
  public static final class Builder {
    private final ImmutableSet.Builder<Class<? extends FragmentOptions>> optionsClasses =
        ImmutableSet.builder();
    private final ImmutableSet.Builder<Class<? extends Fragment>> fragmentClasses =
        ImmutableSortedSet.orderedBy(FragmentClassSet.LEXICAL_FRAGMENT_SORTER);
    private final ImmutableSet.Builder<String> defines = ImmutableSet.builder();
    private final ImmutableSet.Builder<Label> starlarkOptions = ImmutableSet.builder();

    private Builder() {}

    public Builder addOptionsClass(Class<? extends FragmentOptions> optionsClass) {
      optionsClasses.add(optionsClass);
      return this;
    }

    public Builder addOptionsClasses(Iterable<Class<? extends FragmentOptions>> optionsClasses) {
      this.optionsClasses.addAll(optionsClasses);
      return this;
    }

    public Builder addFragmentClasses(Iterable<Class<? extends Fragment>> fragmentClasses) {
      this.fragmentClasses.addAll(fragmentClasses);
      return this;
    }

    public Builder addDefine(String define) {
      defines.add(define);
      return this;
    }

    public Builder addDefines(Iterable<String> defines) {
      this.defines.addAll(defines);
      return this;
    }

    public Builder addStarlarkOption(Label starlarkOption) {
      starlarkOptions.add(starlarkOption);
      return this;
    }

    public Builder addStarlarkOptions(Iterable<Label> starlarkOptions) {
      this.starlarkOptions.addAll(starlarkOptions);
      return this;
    }

    public Builder merge(RequiredConfigFragmentsProvider provider) {
      optionsClasses.addAll(provider.optionsClasses);
      fragmentClasses.addAll(provider.fragmentClasses);
      defines.addAll(provider.defines);
      starlarkOptions.addAll(provider.starlarkOptions);
      return this;
    }

    public RequiredConfigFragmentsProvider build() {
      ImmutableSet<Class<? extends FragmentOptions>> optionsClasses = this.optionsClasses.build();
      ImmutableSet<Class<? extends Fragment>> fragmentClasses = this.fragmentClasses.build();
      ImmutableSet<String> defines = this.defines.build();
      ImmutableSet<Label> starlarkOptions = this.starlarkOptions.build();
      if (optionsClasses.isEmpty()
          && fragmentClasses.isEmpty()
          && defines.isEmpty()
          && starlarkOptions.isEmpty()) {
        return EMPTY;
      }
      return new RequiredConfigFragmentsProvider(
          optionsClasses, FragmentClassSet.of(fragmentClasses), defines, starlarkOptions);
    }
  }
}
