// 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.runtime.commands;

import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.pkgcache.PackageCacheOptions;
import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
import com.google.devtools.build.lib.runtime.BlazeCommand;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.runtime.CommonCommandOptions;
import com.google.devtools.build.lib.runtime.ProjectFile;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.util.ExitCode;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.common.options.OptionPriority;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParsingException;
import com.google.devtools.common.options.OptionsProvider;

import java.util.List;

/**
 * Provides support for implementations for {@link BlazeCommand} to work with {@link ProjectFile}.
 */
public final class ProjectFileSupport {
  static final String PROJECT_FILE_PREFIX = "+";
  
  private ProjectFileSupport() {}

  /**
   * Reads any project files specified on the command line and updates the options parser
   * accordingly. If project files cannot be read or if they contain unparsable options, or if they
   * are not enabled, then it throws an exception instead.
   */
  public static void handleProjectFiles(CommandEnvironment env, OptionsParser optionsParser,
      String command) throws AbruptExitException {
    BlazeRuntime runtime = env.getRuntime();
    List<String> targets = optionsParser.getResidue();
    ProjectFile.Provider projectFileProvider = runtime.getProjectFileProvider();
    if (projectFileProvider != null && !targets.isEmpty()
        && targets.get(0).startsWith(PROJECT_FILE_PREFIX)) {
      if (targets.size() > 1) {
        throw new AbruptExitException("Cannot handle more than one +<file> argument yet",
            ExitCode.COMMAND_LINE_ERROR);
      }
      if (!optionsParser.getOptions(CommonCommandOptions.class).allowProjectFiles) {
        throw new AbruptExitException("project file support is not enabled",
            ExitCode.COMMAND_LINE_ERROR);
      }
      // TODO(bazel-team): This is currently treated as a path relative to the workspace - if the
      // cwd is a subdirectory of the workspace, that will be surprising, and we should interpret it
      // relative to the cwd instead.
      PathFragment projectFilePath = new PathFragment(targets.get(0).substring(1));
      List<Path> packagePath = PathPackageLocator.create(
          runtime.getOutputBase(),
          optionsParser.getOptions(PackageCacheOptions.class).packagePath,
          env.getReporter(),
          runtime.getWorkspace(),
          env.getWorkingDirectory()).getPathEntries();
      ProjectFile projectFile = projectFileProvider.getProjectFile(packagePath, projectFilePath);
      env.getReporter().handle(Event.info("Using " + projectFile.getName()));

      try {
        optionsParser.parse(
            OptionPriority.RC_FILE, projectFile.getName(), projectFile.getCommandLineFor(command));
      } catch (OptionsParsingException e) {
        throw new AbruptExitException(e.getMessage(), ExitCode.COMMAND_LINE_ERROR);
      }
      env.getEventBus().post(new GotProjectFileEvent(projectFile.getName()));
    }
  }

  /**
   * Returns a list of targets from the options residue. If a project file is supplied as the first
   * argument, it will be ignored, on the assumption that handleProjectFiles() has been called to
   * process it.
   */
  public static List<String> getTargets(BlazeRuntime runtime, OptionsProvider options) {
    List<String> targets = options.getResidue();
    if (runtime.getProjectFileProvider() != null && !targets.isEmpty()
        && targets.get(0).startsWith(PROJECT_FILE_PREFIX)) {
      return targets.subList(1, targets.size());
    }
    return targets;
  }
}
