//===-- 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"

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());
      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.");
      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.");
      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.");
      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;
}
