// Copyright 2017 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 com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.configuredtargets.AbstractConfiguredTarget;
import com.google.devtools.build.lib.collect.nestedset.Depset;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.packages.BuiltinProvider;
import com.google.devtools.build.lib.packages.NativeInfo;
import com.google.devtools.build.lib.starlarkbuildapi.DefaultInfoApi;
import javax.annotation.Nullable;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkThread;
import net.starlark.java.syntax.Location;

/** DefaultInfo is provided by all targets implicitly and contains all standard fields. */
@Immutable
public abstract class DefaultInfo extends NativeInfo implements DefaultInfoApi {

  /**
   * Singleton instance of the provider type for {@link DefaultInfo}.
   */
  public static final DefaultInfoProvider PROVIDER = new DefaultInfoProvider();

  @Override
  public DefaultInfoProvider getProvider() {
    return PROVIDER;
  }

  private DefaultInfo() {}

  private DefaultInfo(Location loc) {
    super(loc);
  }

  /**
   * Returns a set of runfiles acting as both the data runfiles and the default runfiles.
   *
   * <p>This is kept for legacy reasons.
   */
  public abstract Runfiles getStatelessRunfiles();

  @Override
  public abstract Runfiles getDataRunfiles();

  @Override
  public abstract Runfiles getDefaultRunfiles();

  /**
   * If the rule producing this info object is marked 'executable' or 'test', this is an artifact
   * representing the file that should be executed to run the target. This is null otherwise.
   */
  public abstract Artifact getExecutable();

  @Override
  public abstract FilesToRunProvider getFilesToRun();

  /** Constructs an optimised DefaultInfo for native targets. */
  public static DefaultInfo build(AbstractConfiguredTarget target) {
    return new DelegatingDefaultInfo(target);
  }

  /** Default implementation of DefaultInfo object for Starlark targets. */
  private static class DefaultDefaultInfo extends DefaultInfo {
    private final Depset files;
    private final Runfiles runfiles;
    private final Runfiles dataRunfiles;
    private final Runfiles defaultRunfiles;
    private final Artifact executable;
    private final FilesToRunProvider filesToRunProvider;

    private DefaultDefaultInfo(
        Location loc,
        Depset files,
        Runfiles runfiles,
        Runfiles dataRunfiles,
        Runfiles defaultRunfiles,
        Artifact executable,
        @Nullable FilesToRunProvider filesToRunProvider) {
      super(loc);
      this.files = files;
      this.runfiles = runfiles;
      this.dataRunfiles = dataRunfiles;
      this.defaultRunfiles = defaultRunfiles;
      this.executable = executable;
      this.filesToRunProvider = filesToRunProvider;
    }

    @Override
    public Depset getFiles() {
      return files;
    }

    @Override
    public FilesToRunProvider getFilesToRun() {
      return filesToRunProvider;
    }

    @Override
    public Runfiles getStatelessRunfiles() {
      return runfiles;
    }

    @Override
    public Runfiles getDataRunfiles() {
      return dataRunfiles;
    }

    @Override
    public Runfiles getDefaultRunfiles() {
      if (dataRunfiles == null && defaultRunfiles == null) {
        // This supports the legacy Starlark runfiles constructor -- if the 'runfiles' attribute
        // is used, then default_runfiles will return all runfiles.
        return runfiles;
      } else {
        return defaultRunfiles;
      }
    }

    @Override
    public Artifact getExecutable() {
      return executable;
    }
  }

  /** Optimised implementation of DefaultInfo object for native targets. */
  private static class DelegatingDefaultInfo extends DefaultInfo {
    private final AbstractConfiguredTarget target;

    DelegatingDefaultInfo(AbstractConfiguredTarget target) {
      this.target = target;
    }

    @Nullable
    @Override
    public Depset getFiles() {
      return Depset.of(Artifact.TYPE, target.getProvider(FileProvider.class).getFilesToBuild());
    }

    @Nullable
    @Override
    public FilesToRunProvider getFilesToRun() {
      return target.getProvider(FilesToRunProvider.class);
    }

    @Nullable
    @Override
    public Runfiles getDataRunfiles() {
      RunfilesProvider runfilesProvider = target.getProvider(RunfilesProvider.class);
      return (runfilesProvider == null) ? Runfiles.EMPTY : runfilesProvider.getDataRunfiles();
    }

    @Nullable
    @Override
    public Runfiles getDefaultRunfiles() {
      RunfilesProvider runfilesProvider = target.getProvider(RunfilesProvider.class);
      return (runfilesProvider == null) ? Runfiles.EMPTY : runfilesProvider.getDefaultRunfiles();
    }

    @Override
    public Runfiles getStatelessRunfiles() {
      return null;
    }

    @Override
    public Artifact getExecutable() {
      return target.getProvider(FilesToRunProvider.class).getExecutable();
    }
  }

  /**
   * Provider implementation for {@link DefaultInfoApi}.
   */
  public static class DefaultInfoProvider extends BuiltinProvider<DefaultInfo>
      implements DefaultInfoApi.DefaultInfoApiProvider<Runfiles, Artifact> {
    private DefaultInfoProvider() {
      super("DefaultInfo", DefaultInfo.class);
    }

    @Override
    public DefaultInfoApi constructor(
        Object files,
        Object runfilesObj,
        Object dataRunfilesObj,
        Object defaultRunfilesObj,
        Object executable,
        StarlarkThread thread)
        throws EvalException {

      Runfiles statelessRunfiles = castNoneToNull(Runfiles.class, runfilesObj);
      Runfiles dataRunfiles = castNoneToNull(Runfiles.class, dataRunfilesObj);
      Runfiles defaultRunfiles = castNoneToNull(Runfiles.class, defaultRunfilesObj);

      if ((statelessRunfiles != null) && (dataRunfiles != null || defaultRunfiles != null)) {
        throw Starlark.errorf(
            "Cannot specify the provider 'runfiles' together with 'data_runfiles' or"
                + " 'default_runfiles'");
      }

      return new DefaultDefaultInfo(
          thread.getCallerLocation(),
          castNoneToNull(Depset.class, files),
          statelessRunfiles,
          dataRunfiles,
          defaultRunfiles,
          castNoneToNull(Artifact.class, executable),
          null);
    }
  }

  private static <T> T castNoneToNull(Class<T> clazz, Object value) {
    if (value == Starlark.NONE) {
      return null;
    } else {
      return clazz.cast(value);
    }
  }
}
