//===-- 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/Target/ThreadPlan.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 char *class_name,
                                       const StructuredDataImpl &args_data)
    : ThreadPlan(ThreadPlan::eKindPython, "Script based Thread Plan", thread,
                 eVoteNoOpinion, eVoteNoOpinion),
      m_class_name(class_name), m_args_data(args_data), 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();
}

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_class_name, this->shared_from_this(), m_args_data);
    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_LOGF(log, "%s called on Scripted Thread Plan: %s )",
            LLVM_PRETTY_FUNCTION, m_class_name.c_str());

  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_LOGF(log, "%s called on Scripted Thread Plan: %s )",
            LLVM_PRETTY_FUNCTION, m_class_name.c_str());

  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_LOGF(log, "%s called on Scripted Thread Plan: %s )",
            LLVM_PRETTY_FUNCTION, m_class_name.c_str());

  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_LOGF(log, "%s called on Scripted Thread Plan: %s )",
            LLVM_PRETTY_FUNCTION, m_class_name.c_str());
  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_LOGF(log, "%s called on Scripted Thread Plan: %s )",
            LLVM_PRETTY_FUNCTION, m_class_name.c_str());
  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_LOGF(log, "%s called on Scripted Thread Plan: %s )",
            LLVM_PRETTY_FUNCTION, m_class_name.c_str());
  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->Printf("Scripted thread plan implemented by class %s.",
                  m_class_name.c_str());
      } 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->Printf("Scripted thread plan implemented by class %s.",
              m_class_name.c_str());
  s->PutCString(m_stop_description.GetData());
}

// The ones below are not currently exported to Python.
bool ScriptedThreadPlan::WillStop() {
  Log *log = GetLog(LLDBLog::Thread);
  LLDB_LOGF(log, "%s called on Scripted Thread Plan: %s )",
            LLVM_PRETTY_FUNCTION, m_class_name.c_str());
  return true;
}

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