// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CROS_DISKS_PROCESS_H_
#define CROS_DISKS_PROCESS_H_

#include <string>
#include <vector>

#include <base/files/scoped_file.h>
#include <base/macros.h>
#include <base/strings/string_piece.h>

#include <gtest/gtest_prod.h>

namespace cros_disks {

// A base class for executing a process.
//
// TODO(crbug.com/1003654) This base class is not feature complete yet.
class Process {
 public:
  // Invalid process ID assigned to a process that has not started.
  static const pid_t kInvalidProcessId;

  static const int kInvalidFD;

  virtual ~Process();

  // Adds an argument to the end of the argument list.
  // Precondition: Start() has not been called yet.
  void AddArgument(std::string argument);

  // Adds a variable to the environment that will be passed to the process.
  // Precondition: Start() has not been called yet.
  // Precondition: `name` is not empty and doesn't contain '='.
  void AddEnvironmentVariable(base::StringPiece name, base::StringPiece value);

  // Starts the process. The started process has its stdin, stdout and stderr
  // connected to /dev/null. Returns true in case of success. Once started, the
  // process can be waiting for to finish using Wait().
  bool Start();

  // Waits for the process to finish and returns its exit status.
  int Wait();

  // Checks if the process finished.
  bool IsFinished();

  // Starts a process, captures its output and waits for it to finish. Returns
  // the same exit status as Wait().
  //
  // Precondition: output is non-null
  int Run(std::vector<std::string>* output);

  pid_t pid() const { return pid_; }

  const std::vector<std::string>& arguments() const { return arguments_; }
  const std::vector<std::string>& environment() const { return environment_; }

 protected:
  Process();

  // Gets the arguments used to start the process. This method calls
  // BuildArgumentsArray() to build |arguments_array_| only once (i.e. when
  // |arguments_array_| is empty). Once |arguments_array_| is built, subsequent
  // calls to AddArgument() are not allowed. The returned array of arguments is
  // owned by this Process object.
  char* const* GetArguments();

  // Gets the environment to pass to the subprocess. The returned array of
  // environment variables is owned by this Process object.
  char* const* GetEnvironment();

  // Starts a process, and connects to its stdin, stdout and stderr the given
  // file descriptors.
  //
  // Returns the PID of the started process, or -1 in case of error.
  virtual pid_t StartImpl(base::ScopedFD in_fd,
                          base::ScopedFD out_fd,
                          base::ScopedFD err_fd) = 0;

  // Once either WaitImpl() or WaitNonBlockingImpl() has returned a nonnegative
  // exit status, none of these methods is called again.

  // Waits for the process to finish and returns its nonnegative exit status.
  virtual int WaitImpl() = 0;

  // Checks if the process has finished and returns its nonnegative exit status,
  // or -1 if the process is still running.
  virtual int WaitNonBlockingImpl() = 0;

 private:
  // Starts the process. The started process has its stdin, stdout and stderr
  // redirected to the given file descriptors. Returns true in case of success.
  bool Start(base::ScopedFD in_fd,
             base::ScopedFD out_fd,
             base::ScopedFD err_fd);

  // Waits for process to finish collecting process' stdout and stderr
  // output and fills interleaved version of it.
  void Communicate(std::vector<std::string>* output,
                   base::ScopedFD out_fd,
                   base::ScopedFD err_fd);

  // Builds |arguments_array_| from |arguments_|. Existing values of
  // |arguments_array_| are overridden.
  void BuildArgumentsArray();

  bool finished() const { return status_ >= 0; }

  // Process arguments.
  std::vector<std::string> arguments_;
  std::vector<char*> arguments_array_;

  // Extra environment variables.
  std::vector<std::string> environment_;

  // Full environment for the subprocess.
  std::vector<char*> environment_array_;

  // Process ID (default to kInvalidProcessId when the process has not started).
  pid_t pid_ = kInvalidProcessId;

  // Exit status. A nonnegative value indicates that the process has finished.
  int status_ = -1;

  FRIEND_TEST(ProcessTest, GetArguments);
  FRIEND_TEST(ProcessTest, GetArgumentsWithNoArgumentsAdded);

  DISALLOW_COPY_AND_ASSIGN(Process);
};

}  // namespace cros_disks

#endif  // CROS_DISKS_PROCESS_H_
