// 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.rules.android.databinding;

import static com.google.devtools.build.lib.rules.android.AndroidSkylarkData.fromNoneable;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.packages.BuiltinProvider;
import com.google.devtools.build.lib.packages.NativeInfo;
import com.google.devtools.build.lib.skylarkbuildapi.android.DataBindingV2ProviderApi;
import com.google.devtools.build.lib.syntax.Depset;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.Sequence;
import javax.annotation.Nullable;

/**
 * A provider that exposes this enables <a
 * href="https://developer.android.com/topic/libraries/data-binding/index.html">data binding</a>
 * version 2 on its resource processing and Java compilation.
 */
public final class DataBindingV2Provider extends NativeInfo
    implements DataBindingV2ProviderApi<Artifact> {

  public static final Provider PROVIDER = new Provider();

  private final ImmutableList<Artifact> classInfos;

  private final ImmutableList<Artifact> setterStores;

  private final NestedSet<Artifact> transitiveBRFiles;

  /**
   * The label and java package of this rule and any rules that this rule exports.
   */
  @Nullable
  private final ImmutableList<LabelJavaPackagePair> labelAndJavaPackages;

  private final NestedSet<LabelJavaPackagePair> transitiveLabelAndJavaPackages;

  public DataBindingV2Provider(
      ImmutableList<Artifact> classInfos,
      ImmutableList<Artifact> setterStores,
      NestedSet<Artifact> transitiveBRFiles,
      ImmutableList<LabelJavaPackagePair> labelAndJavaPackages,
      NestedSet<LabelJavaPackagePair> transitiveLabelAndJavaPackages) {
    super(PROVIDER);
    this.classInfos = classInfos;
    this.setterStores = setterStores;
    this.transitiveBRFiles = transitiveBRFiles;
    this.labelAndJavaPackages = labelAndJavaPackages;
    this.transitiveLabelAndJavaPackages = transitiveLabelAndJavaPackages;
  }

  @Override
  public ImmutableList<Artifact> getClassInfos() {
    return classInfos;
  }

  @Override
  public ImmutableList<Artifact> getSetterStores() {
    return setterStores;
  }

  @Override
  public Depset /*<Artifact>*/ getTransitiveBRFilesForStarlark() {
    return Depset.of(Artifact.TYPE, transitiveBRFiles);
  }

  public NestedSet<Artifact> getTransitiveBRFiles() {
    return transitiveBRFiles;
  }

  @Override
  @Nullable
  public ImmutableList<LabelJavaPackagePair> getLabelAndJavaPackages() {
    return labelAndJavaPackages;
  }

  @Override
  public Depset /*<LabelJavaPackagePair>*/ getTransitiveLabelAndJavaPackagesForStarlark() {
    return Depset.of(LabelJavaPackagePair.class, transitiveLabelAndJavaPackages);
  }

  public NestedSet<LabelJavaPackagePair> getTransitiveLabelAndJavaPackages() {
    return transitiveLabelAndJavaPackages;
  }

  public static DataBindingV2Provider createProvider(
      Artifact setterStoreFile,
      Artifact classInfoFile,
      Artifact brFile,
      String label,
      String javaPackage,
      // ugh these *Api types do not help one bit
      Iterable<? extends DataBindingV2ProviderApi<Artifact>> databindingV2ProvidersInDeps,
      Iterable<? extends DataBindingV2ProviderApi<Artifact>> databindingV2ProvidersInExports) {

    ImmutableList.Builder<Artifact> setterStoreFiles = ImmutableList.builder();
    if (setterStoreFile != null) {
      setterStoreFiles.add(setterStoreFile);
    }

    ImmutableList.Builder<Artifact> classInfoFiles = ImmutableList.builder();
    if (classInfoFile != null) {
      classInfoFiles.add(classInfoFile);
    }

    NestedSetBuilder<Artifact> brFiles = NestedSetBuilder.stableOrder();
    if (brFile != null) {
      brFiles.add(brFile);
    }

    NestedSetBuilder<LabelJavaPackagePair> transitiveLabelAndJavaPackages =
        NestedSetBuilder.stableOrder();
    ImmutableList.Builder<LabelJavaPackagePair> labelAndJavaPackages = ImmutableList.builder();

    if (label != null && javaPackage != null) {
      LabelJavaPackagePair labelAndJavaPackage = new LabelJavaPackagePair(label, javaPackage);
      labelAndJavaPackages.add(labelAndJavaPackage);
      transitiveLabelAndJavaPackages.add(labelAndJavaPackage);
    }

    if (databindingV2ProvidersInDeps != null) {

      for (DataBindingV2ProviderApi<Artifact> p : databindingV2ProvidersInDeps) {
        DataBindingV2Provider provider = (DataBindingV2Provider) p;
        brFiles.addTransitive(provider.getTransitiveBRFiles());
        transitiveLabelAndJavaPackages.addTransitive(provider.getTransitiveLabelAndJavaPackages());
      }
    }

    if (databindingV2ProvidersInExports != null) {

      // Add all of the information from providers from exported targets, so that targets which
      // depend on this target appear to depend on the exported targets.
      for (DataBindingV2ProviderApi<Artifact> p : databindingV2ProvidersInExports) {
        DataBindingV2Provider provider = (DataBindingV2Provider) p;
        setterStoreFiles.addAll(provider.getSetterStores());
        classInfoFiles.addAll(provider.getClassInfos());
        brFiles.addTransitive(provider.getTransitiveBRFiles());
        labelAndJavaPackages.addAll(provider.getLabelAndJavaPackages());
        transitiveLabelAndJavaPackages.addTransitive(provider.getTransitiveLabelAndJavaPackages());
      }
    }

    return new DataBindingV2Provider(
        classInfoFiles.build(),
        setterStoreFiles.build(),
        brFiles.build(),
        labelAndJavaPackages.build(),
        transitiveLabelAndJavaPackages.build());
  }

  /** The provider can construct the DataBindingV2Provider provider. */
  public static class Provider extends BuiltinProvider<DataBindingV2Provider>
      implements DataBindingV2ProviderApi.Provider<Artifact> {

    private Provider() {
      super(NAME, DataBindingV2Provider.class);
    }

    @Override
    public DataBindingV2ProviderApi<Artifact> createInfo(
        Object setterStoreFile,
        Object classInfoFile,
        Object brFile,
        Object label,
        Object javaPackage,
        Sequence<?> databindingV2ProvidersInDeps, // <DataBindingV2Provider>
        Sequence<?> databindingV2ProvidersInExports) // <DataBindingV2Provider>
        throws EvalException {

      return createProvider(
          fromNoneable(setterStoreFile, Artifact.class),
          fromNoneable(classInfoFile, Artifact.class),
          fromNoneable(brFile, Artifact.class),
          fromNoneable(label, String.class),
          fromNoneable(javaPackage, String.class),
          databindingV2ProvidersInDeps == null
              ? null
              : ImmutableList.copyOf(
                  databindingV2ProvidersInDeps.getContents(
                      DataBindingV2Provider.class, "databinding_v2_providers_in_deps")),
          databindingV2ProvidersInExports == null
              ? null
              : ImmutableList.copyOf(
                  databindingV2ProvidersInExports.getContents(
                      DataBindingV2Provider.class, "databinding_v2_providers_in_exports")));
    }
  }
}
