// Copyright 2018 The Fuchsia 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 "src/developer/debug/zxdb/client/target_impl.h"

#include <lib/syslog/cpp/macros.h>

#include <sstream>

#include "src/developer/debug/shared/logging/logging.h"
#include "src/developer/debug/shared/message_loop.h"
#include "src/developer/debug/shared/zx_status.h"
#include "src/developer/debug/zxdb/client/process_impl.h"
#include "src/developer/debug/zxdb/client/remote_api.h"
#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/client/setting_schema_definition.h"
#include "src/developer/debug/zxdb/client/system.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace zxdb {

TargetImpl::TargetImpl(System* system)
    : Target(system->session()),
      system_(system),
      symbols_(system->GetSymbols()),
      impl_weak_factory_(this) {
  settings_.set_fallback(&system_->settings());
}

TargetImpl::~TargetImpl() {
  // If the process is still running, make sure we broadcast terminated notifications before
  // deleting everything.
  ImplicitlyDetach();
}

std::unique_ptr<TargetImpl> TargetImpl::Clone(System* system) {
  auto result = std::make_unique<TargetImpl>(system);
  result->args_ = args_;
  result->symbols_ = symbols_;
  return result;
}

void TargetImpl::ProcessCreatedInJob(uint64_t koid, const std::string& process_name) {
  FX_DCHECK(state_ == State::kNone);
  FX_DCHECK(!process_.get());  // Shouldn't have a process.

  state_ = State::kRunning;
  process_ = CreateProcessImpl(koid, process_name, Process::StartType::kAttach);

  for (auto& observer : session()->process_observers())
    observer.DidCreateProcess(process_.get(), true);
}

void TargetImpl::ProcessCreatedAsComponent(uint64_t koid, const std::string& process_name) {
  FX_DCHECK(state_ == State::kNone);
  FX_DCHECK(!process_.get());

  state_ = State::kRunning;
  process_ = CreateProcessImpl(koid, process_name, Process::StartType::kComponent);

  for (auto& observer : session()->process_observers())
    observer.DidCreateProcess(process_.get(), false);
}

void TargetImpl::CreateProcessForTesting(uint64_t koid, const std::string& process_name) {
  FX_DCHECK(state_ == State::kNone);
  state_ = State::kStarting;
  OnLaunchOrAttachReply(Callback(), Err(), koid, 0, process_name);
}

void TargetImpl::ImplicitlyDetach() {
  if (GetProcess()) {
    OnKillOrDetachReply(ProcessObserver::DestroyReason::kDetach, Err(), 0,
                        [](fxl::WeakPtr<Target>, const Err&) {});
  }
}

Target::State TargetImpl::GetState() const { return state_; }

Process* TargetImpl::GetProcess() const { return process_.get(); }

const TargetSymbols* TargetImpl::GetSymbols() const { return &symbols_; }

const std::vector<std::string>& TargetImpl::GetArgs() const { return args_; }

void TargetImpl::SetArgs(std::vector<std::string> args) { args_ = std::move(args); }

void TargetImpl::Launch(Callback callback) {
  Err err;
  if (state_ != State::kNone)
    err = Err("Can't launch, program is already running or starting.");
  else if (args_.empty())
    err = Err("No program specified to launch.");

  if (err.has_error()) {
    // Avoid reentering caller to dispatch the error.
    debug_ipc::MessageLoop::Current()->PostTask(
        FROM_HERE, [callback = std::move(callback), err, weak_ptr = GetWeakPtr()]() mutable {
          callback(std::move(weak_ptr), err);
        });
    return;
  }

  state_ = State::kStarting;

  debug_ipc::LaunchRequest request;
  request.inferior_type = debug_ipc::InferiorType::kBinary;
  request.argv = args_;
  session()->remote_api()->Launch(
      request, [callback = std::move(callback), weak_target = impl_weak_factory_.GetWeakPtr()](
                   const Err& err, debug_ipc::LaunchReply reply) mutable {
        TargetImpl::OnLaunchOrAttachReplyThunk(weak_target, std::move(callback), err,
                                               reply.process_id, reply.status, reply.process_name);
      });
}

void TargetImpl::Kill(Callback callback) {
  if (!process_.get()) {
    debug_ipc::MessageLoop::Current()->PostTask(
        FROM_HERE, [callback = std::move(callback), weak_ptr = GetWeakPtr()]() mutable {
          callback(std::move(weak_ptr), Err("Error killing: No process."));
        });
    return;
  }

  debug_ipc::KillRequest request;
  request.process_koid = process_->GetKoid();
  session()->remote_api()->Kill(
      request, [callback = std::move(callback), weak_target = impl_weak_factory_.GetWeakPtr()](
                   const Err& err, debug_ipc::KillReply reply) mutable {
        if (weak_target) {
          weak_target->OnKillOrDetachReply(ProcessObserver::DestroyReason::kKill, err, reply.status,
                                           std::move(callback));
        } else {
          // The reply that the process was launched came after the local objects were destroyed.
          // We're still OK to dispatch either way.
          callback(weak_target, err);
        }
      });
}

void TargetImpl::Attach(uint64_t koid, Callback callback) {
  if (state_ != State::kNone) {
    // Avoid reentering caller to dispatch the error.
    debug_ipc::MessageLoop::Current()->PostTask(FROM_HERE, [callback = std::move(callback),
                                                            weak_ptr = GetWeakPtr()]() mutable {
      callback(std::move(weak_ptr), Err("Can't attach, program is already running or starting."));
    });
    return;
  }

  state_ = State::kAttaching;

  debug_ipc::AttachRequest request;
  request.koid = koid;
  session()->remote_api()->Attach(
      request,
      [koid, callback = std::move(callback), weak_target = impl_weak_factory_.GetWeakPtr()](
          const Err& err, debug_ipc::AttachReply reply) mutable {
        OnLaunchOrAttachReplyThunk(std::move(weak_target), std::move(callback), err, koid,
                                   reply.status, reply.name);
      });
}

void TargetImpl::Detach(Callback callback) {
  if (!process_.get()) {
    debug_ipc::MessageLoop::Current()->PostTask(
        FROM_HERE, [callback = std::move(callback), weak_ptr = GetWeakPtr()]() mutable {
          callback(std::move(weak_ptr), Err("Error detaching: No process."));
        });
    return;
  }

  debug_ipc::DetachRequest request;
  request.koid = process_->GetKoid();
  session()->remote_api()->Detach(
      request, [callback = std::move(callback), weak_target = impl_weak_factory_.GetWeakPtr()](
                   const Err& err, debug_ipc::DetachReply reply) mutable {
        if (weak_target) {
          weak_target->OnKillOrDetachReply(ProcessObserver::DestroyReason::kDetach, err,
                                           reply.status, std::move(callback));
        } else {
          // The reply that the process was launched came after the local objects were destroyed.
          // We're still OK to dispatch either way.
          callback(weak_target, err);
        }
      });
}

void TargetImpl::OnProcessExiting(int return_code) {
  FX_DCHECK(state_ == State::kRunning);
  state_ = State::kNone;

  for (auto& observer : session()->process_observers())
    observer.WillDestroyProcess(process_.get(), ProcessObserver::DestroyReason::kExit, return_code);

  process_.reset();
}

// static
void TargetImpl::OnLaunchOrAttachReplyThunk(fxl::WeakPtr<TargetImpl> target, Callback callback,
                                            const Err& err, uint64_t koid,
                                            debug_ipc::zx_status_t status,
                                            const std::string& process_name) {
  if (target) {
    target->OnLaunchOrAttachReply(std::move(callback), err, koid, status, process_name);
  } else {
    // The reply that the process was launched came after the local objects were destroyed.
    if (err.has_error()) {
      // Process not launched, forward the error.
      callback(target, err);
    } else {
      // TODO(brettw) handle this more gracefully. Maybe kill the remote
      // process?
      callback(target, Err("Warning: process launch race, extra process is "
                           "likely running."));
    }
  }
}

void TargetImpl::OnLaunchOrAttachReply(Callback callback, const Err& err, uint64_t koid,
                                       debug_ipc::zx_status_t status,
                                       const std::string& process_name) {
  FX_DCHECK(state_ == State::kAttaching || state_ == State::kStarting);
  FX_DCHECK(!process_.get());  // Shouldn't have a process.

  Err issue_err;  // Error to send in callback.
  if (err.has_error()) {
    // Error from transport.
    state_ = State::kNone;
    issue_err = err;
  } else if (status != 0) {
    state_ = State::kNone;
    return HandleAttachStatus(std::move(callback), koid, status, process_name);
  } else {
    Process::StartType start_type =
        state_ == State::kAttaching ? Process::StartType::kAttach : Process::StartType::kLaunch;
    state_ = State::kRunning;
    process_ = CreateProcessImpl(koid, process_name, start_type);
  }

  if (callback)
    callback(GetWeakPtr(), issue_err);

  if (state_ == State::kRunning) {
    for (auto& observer : session()->process_observers())
      observer.DidCreateProcess(process_.get(), false);
  }
}

void TargetImpl::HandleAttachStatus(Callback callback, uint64_t koid, debug_ipc::zx_status_t status,
                                    const std::string& process_name) {
  Err err;
  if (status == debug_ipc::kZxErrIO) {
    err = Err("Error launching: Binary not found [%s]", debug_ipc::ZxStatusToString(status));
  } else if (status == debug_ipc::kZxErrAlreadyBound) {
    // Already bound means that the user is trying to re-attach, so we need to ask for the "status"
    // for that particular process.
    //
    // We avoid sending the initial attach request as in most cases the agent won't be connected to
    // the process we want to attach to, so it's not really efficient to pre-track this case.
    debug_ipc::ProcessStatusRequest request = {};
    request.process_koid = koid;

    DEBUG_LOG(Session) << "Re-attaching to process " << process_name << " (" << koid << ").";
    session()->remote_api()->ProcessStatus(
        request, [target = GetWeakPtr(), callback = std::move(callback), process_name](
                     const Err& err, debug_ipc::ProcessStatusReply reply) mutable {
          if (!target)
            return;

          if (err.has_error())
            return callback(target, err);

          if (reply.status != debug_ipc::kZxOk) {
            Err error("Could not attach to process %s: %s", process_name.c_str(),
                      debug_ipc::ZxStatusToString(reply.status));
            return callback(target, err);
          }

          return callback(target, Err());
        });
    return;
  } else {
    err = Err(
        fxl::StringPrintf("Error launching, status = %s.", debug_ipc::ZxStatusToString(status)));
  }

  callback(GetWeakPtr(), err);
}

void TargetImpl::OnKillOrDetachReply(ProcessObserver::DestroyReason reason, const Err& err,
                                     int32_t status, Callback callback) {
  FX_DCHECK(process_.get());  // Should have a process.

  Err issue_err;  // Error to send in callback.
  if (err.has_error()) {
    // Error from transport.
    state_ = State::kNone;
    issue_err = err;
  } else if (status != 0) {
    // Error from detaching.
    // TODO(davemoore): Not sure what state the target should be if we error upon detach.
    issue_err = Err(fxl::StringPrintf("Error %sing, status = %s.",
                                      ProcessObserver::DestroyReasonToString(reason),
                                      debug_ipc::ZxStatusToString(status)));
  } else {
    // Successfully detached.
    state_ = State::kNone;

    // Keep the process alive for the observer call, but remove it from the target as per the
    // observer specification.
    for (auto& observer : session()->process_observers())
      observer.WillDestroyProcess(process_.get(), reason, 0);

    process_.reset();
  }

  callback(GetWeakPtr(), issue_err);
}

std::unique_ptr<ProcessImpl> TargetImpl::CreateProcessImpl(uint64_t koid, const std::string& name,
                                                           Process::StartType start_type) {
  return std::make_unique<ProcessImpl>(this, koid, name, Process::StartType::kAttach);
}

}  // namespace zxdb
