// Copyright (c) 2013 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.

#include "shill/external_task.h"

#include <base/bind.h>
#include <base/bind_helpers.h>

#include "shill/error.h"
#include "shill/event_dispatcher.h"
#include "shill/process_killer.h"

namespace shill {

using base::FilePath;
using std::map;
using std::string;
using std::vector;

ExternalTask::ExternalTask(
    ControlInterface *control,
    GLib *glib,
    const base::WeakPtr<RPCTaskDelegate> &task_delegate,
    const base::Callback<void(pid_t, int)> &death_callback)
    : control_(control),
      glib_(glib),
      process_killer_(ProcessKiller::GetInstance()),
      task_delegate_(task_delegate),
      death_callback_(death_callback),
      pid_(0),
      child_watch_tag_(0) {
  CHECK(task_delegate_);
}

ExternalTask::~ExternalTask() {
  ExternalTask::Stop();
}

void ExternalTask::DestroyLater(EventDispatcher *dispatcher) {
  // Passes ownership of |this| to Destroy.
  dispatcher->PostTask(base::Bind(&Destroy, this));
}

bool ExternalTask::Start(const FilePath &program,
                         const vector<string> &arguments,
                         const map<string, string> &environment,
                         Error *error) {
  CHECK(!pid_);
  CHECK(!child_watch_tag_);
  CHECK(!rpc_task_);

  scoped_ptr<RPCTask> local_rpc_task(new RPCTask(control_, this));

  // const_cast is safe here, because exec*() (and SpawnAsync) do not
  // modify the strings passed to them. This isn't captured in the
  // exec*() prototypes, due to limitations in ISO C.
  // http://pubs.opengroup.org/onlinepubs/009695399/functions/exec.html
  vector<char *> process_args;
  process_args.push_back(const_cast<char *>(program.value().c_str()));
  for (const auto &option : arguments) {
    process_args.push_back(const_cast<char *>(option.c_str()));
  }
  process_args.push_back(NULL);

  vector<char *> process_env;
  vector<string> env_vars(local_rpc_task->GetEnvironment());
  for (const auto &env_pair : environment) {
    env_vars.push_back(string(env_pair.first + "=" + env_pair.second));
  }
  for (const auto &env_var : env_vars) {
    // See above regarding const_cast.
    process_env.push_back(const_cast<char *>(env_var.c_str()));
  }
  process_env.push_back(NULL);

  if (!glib_->SpawnAsync(NULL,
                         process_args.data(),
                         process_env.data(),
                         G_SPAWN_DO_NOT_REAP_CHILD,
                         NULL,
                         NULL,
                         &pid_,
                         NULL)) {
    Error::PopulateAndLog(error, Error::kInternalError,
                          string("Unable to spawn: ") + process_args[0]);
    return false;
  }
  child_watch_tag_ = glib_->ChildWatchAdd(pid_, OnTaskDied, this);
  rpc_task_.reset(local_rpc_task.release());
  return true;
}

void ExternalTask::Stop() {
  if (child_watch_tag_) {
    glib_->SourceRemove(child_watch_tag_);
    child_watch_tag_ = 0;
  }
  if (pid_) {
    process_killer_->Kill(pid_, base::Closure());
    pid_ = 0;
  }
  rpc_task_.reset();
}

void ExternalTask::GetLogin(string *user, string *password) {
  return task_delegate_->GetLogin(user, password);
}

void ExternalTask::Notify(const string &event,
                          const map<string, string> &details) {
  return task_delegate_->Notify(event, details);
}

// static
void ExternalTask::OnTaskDied(GPid pid, gint status, gpointer data) {
  LOG(INFO) << __func__ << "(" << pid << ", "  << status << ")";
  ExternalTask *me = reinterpret_cast<ExternalTask *>(data);
  me->child_watch_tag_ = 0;
  CHECK_EQ(pid, me->pid_);
  me->pid_ = 0;
  me->death_callback_.Run(pid, status);
}

// static
void ExternalTask::Destroy(ExternalTask *task) {
  delete task;
}

}  // namespace shill
