//===-- ScriptedThreadPlan.cpp --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/ThreadPlan.h"

#include "lldb/Core/Debugger.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/ScriptedThreadPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.h"
#include "llvm/Support/FormatVariadic.h"

using namespace lldb;
using namespace lldb_private;

ScriptedThreadPlan::ScriptedThreadPlan(
    Thread &thread, const ScriptedMetadata &scripted_metadata)
    : ThreadPlan(ThreadPlan::eKindPython, "Script based Thread Plan", thread,
                 eVoteNoOpinion, eVoteNoOpinion),
      m_scripted_metadata(scripted_metadata), m_did_push(false),
      m_stop_others(false) {
  ScriptInterpreter *interpreter = GetScriptInterpreter();
  if (!interpreter) {
    SetPlanComplete(false);
    // FIXME: error handling
    // error = Status::FromErrorStringWithFormat(
    //     "ScriptedThreadPlan::%s () - ERROR: %s", __FUNCTION__,
    //     "Couldn't get script interpreter");
    return;
  }

  m_interface = interpreter->CreateScriptedThreadPlanInterface();
  if (!m_interface) {
    SetPlanComplete(false);
    // FIXME: error handling
    // error = Status::FromErrorStringWithFormat(
    //     "ScriptedThreadPlan::%s () - ERROR: %s", __FUNCTION__,
    //     "Script interpreter couldn't create Scripted Thread Plan Interface");
    return;
  }

  SetIsControllingPlan(true);
  SetOkayToDiscard(true);
  SetPrivate(false);
}

bool ScriptedThreadPlan::ValidatePlan(Stream *error) {
  if (!m_did_push)
    return true;

  if (!m_implementation_sp) {
    if (error)
      error->Printf("Error constructing Python ThreadPlan: %s",
                    m_error_str.empty() ? "<unknown error>"
                                        : m_error_str.c_str());
    return false;
  }

  return true;
}

ScriptInterpreter *ScriptedThreadPlan::GetScriptInterpreter() {
  return m_process.GetTarget().GetDebugger().GetScriptInterpreter();
}

llvm::StringRef ScriptedThreadPlan::GetScriptClassName() const {
  if (m_interface && m_interface->GetScriptedMetadata())
    return m_interface->GetScriptedMetadata()->GetClassName();
  return "<unknown>";
}

void ScriptedThreadPlan::DidPush() {
  // We set up the script side in DidPush, so that it can push other plans in
  // the constructor, and doesn't have to care about the details of DidPush.
  m_did_push = true;
  if (m_interface) {
    auto obj_or_err = m_interface->CreatePluginObject(m_scripted_metadata,
                                                      this->shared_from_this());
    if (!obj_or_err) {
      m_error_str = llvm::toString(obj_or_err.takeError());
      Debugger::ReportError(
          llvm::formatv("failed to create ScriptedThreadPlan: {0}", m_error_str)
              .str(),
          m_process.GetTarget().GetDebugger().GetID());
      SetPlanComplete(false);
    } else
      m_implementation_sp = *obj_or_err;
  }
}

bool ScriptedThreadPlan::ShouldStop(Event *event_ptr) {
  Log *log = GetLog(LLDBLog::Thread);
  LLDB_LOG(log, "called on Scripted Thread Plan: {0}", GetScriptClassName());

  bool should_stop = true;
  if (m_implementation_sp) {
    auto should_stop_or_err = m_interface->ShouldStop(event_ptr);
    if (!should_stop_or_err) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), should_stop_or_err.takeError(),
                     "Can't call ScriptedThreadPlan::ShouldStop: {0}");
      SetPlanComplete(false);
    } else
      should_stop = *should_stop_or_err;
  }
  return should_stop;
}

bool ScriptedThreadPlan::IsPlanStale() {
  Log *log = GetLog(LLDBLog::Thread);
  LLDB_LOG(log, "called on Scripted Thread Plan: {0}", GetScriptClassName());

  bool is_stale = true;
  if (m_implementation_sp) {
    auto is_stale_or_err = m_interface->IsStale();
    if (!is_stale_or_err) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), is_stale_or_err.takeError(),
                     "Can't call ScriptedThreadPlan::IsStale: {0}");
      SetPlanComplete(false);
    } else
      is_stale = *is_stale_or_err;
  }
  return is_stale;
}

bool ScriptedThreadPlan::DoPlanExplainsStop(Event *event_ptr) {
  Log *log = GetLog(LLDBLog::Thread);
  LLDB_LOG(log, "called on Scripted Thread Plan: {0}", GetScriptClassName());

  bool explains_stop = true;
  if (m_implementation_sp) {
    auto explains_stop_or_error = m_interface->ExplainsStop(event_ptr);
    if (!explains_stop_or_error) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Thread),
                     explains_stop_or_error.takeError(),
                     "Can't call ScriptedThreadPlan::ExplainsStop: {0}");
      SetPlanComplete(false);
    } else
      explains_stop = *explains_stop_or_error;
  }
  return explains_stop;
}

bool ScriptedThreadPlan::MischiefManaged() {
  Log *log = GetLog(LLDBLog::Thread);
  LLDB_LOG(log, "called on Scripted Thread Plan: {0}", GetScriptClassName());
  bool mischief_managed = true;
  if (m_implementation_sp) {
    // I don't really need mischief_managed, since it's simpler to just call
    // SetPlanComplete in should_stop.
    mischief_managed = IsPlanComplete();
    if (mischief_managed) {
      // We need to cache the stop reason here we'll need it in GetDescription.
      GetDescription(&m_stop_description, eDescriptionLevelBrief);
      m_implementation_sp.reset();
    }
  }
  return mischief_managed;
}

lldb::StateType ScriptedThreadPlan::GetPlanRunState() {
  Log *log = GetLog(LLDBLog::Thread);
  LLDB_LOG(log, "called on Scripted Thread Plan: {0}", GetScriptClassName());
  lldb::StateType run_state = eStateRunning;
  if (m_implementation_sp)
    run_state = m_interface->GetRunState();
  return run_state;
}

void ScriptedThreadPlan::GetDescription(Stream *s,
                                        lldb::DescriptionLevel level) {
  Log *log = GetLog(LLDBLog::Thread);
  LLDB_LOG(log, "called on Scripted Thread Plan: {0}", GetScriptClassName());
  if (m_implementation_sp) {
    ScriptInterpreter *script_interp = GetScriptInterpreter();
    if (script_interp) {
      lldb::StreamSP stream = std::make_shared<lldb_private::StreamString>();
      llvm::Error err = m_interface->GetStopDescription(stream);
      if (err) {
        LLDB_LOG_ERROR(
            GetLog(LLDBLog::Thread), std::move(err),
            "Can't call ScriptedThreadPlan::GetStopDescription: {0}");
        s->Format("Scripted thread plan implemented by class {0}.",
                  GetScriptClassName());
      } else
        s->PutCString(
            reinterpret_cast<StreamString *>(stream.get())->GetData());
    }
    return;
  }
  // It's an error not to have a description, so if we get here, we should
  // add something.
  if (m_stop_description.Empty())
    s->Format("Scripted thread plan implemented by class {0}.",
              GetScriptClassName());
  s->PutCString(m_stop_description.GetData());
}

// The ones below are not currently exported to Python.
bool ScriptedThreadPlan::WillStop() {
  Log *log = GetLog(LLDBLog::Thread);
  LLDB_LOG(log, "called on Scripted Thread Plan: {0}", GetScriptClassName());
  return true;
}

bool ScriptedThreadPlan::DoWillResume(lldb::StateType resume_state,
                                      bool current_plan) {
  m_stop_description.Clear();
  return true;
}
