/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmVariableWatchCommand.h"

#include <limits>
#include <memory>
#include <utility>

#include "cmExecutionStatus.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmVariableWatch.h"
#include "cmake.h"

namespace {
struct cmVariableWatchCallbackData
{
  bool InCallback;
  std::string Command;
};

void cmVariableWatchCommandVariableAccessed(const std::string& variable,
                                            int access_type, void* client_data,
                                            const char* newValue,
                                            const cmMakefile* mf)
{
  cmVariableWatchCallbackData* data =
    static_cast<cmVariableWatchCallbackData*>(client_data);

  if (data->InCallback) {
    return;
  }
  data->InCallback = true;

  auto accessString = cmVariableWatch::GetAccessAsString(access_type);

  /// Ultra bad!!
  cmMakefile* makefile = const_cast<cmMakefile*>(mf);

  std::string stack = makefile->GetProperty("LISTFILE_STACK");
  if (!data->Command.empty()) {
    cmListFileFunction newLFF;
    const char* const currentListFile =
      mf->GetDefinition("CMAKE_CURRENT_LIST_FILE");
    const auto fakeLineNo =
      std::numeric_limits<decltype(cmListFileArgument::Line)>::max();
    newLFF.Arguments = {
      { variable, cmListFileArgument::Quoted, fakeLineNo },
      { accessString, cmListFileArgument::Quoted, fakeLineNo },
      { newValue ? newValue : "", cmListFileArgument::Quoted, fakeLineNo },
      { currentListFile, cmListFileArgument::Quoted, fakeLineNo },
      { stack, cmListFileArgument::Quoted, fakeLineNo }
    };
    newLFF.Name = data->Command;
    newLFF.Line = fakeLineNo;
    cmExecutionStatus status(*makefile);
    if (!makefile->ExecuteCommand(newLFF, status)) {
      cmSystemTools::Error(
        cmStrCat("Error in cmake code at\nUnknown:0:\nA command failed "
                 "during the invocation of callback \"",
                 data->Command, "\"."));
    }
  } else {
    makefile->IssueMessage(
      MessageType::LOG,
      cmStrCat("Variable \"", variable, "\" was accessed using ", accessString,
               " with value \"", (newValue ? newValue : ""), "\"."));
  }

  data->InCallback = false;
}

void deleteVariableWatchCallbackData(void* client_data)
{
  cmVariableWatchCallbackData* data =
    static_cast<cmVariableWatchCallbackData*>(client_data);
  delete data;
}

/** This command does not really have a final pass but it needs to
    stay alive since it owns variable watch callback information. */
class FinalAction
{
public:
  /* NOLINTNEXTLINE(performance-unnecessary-value-param) */
  FinalAction(cmMakefile* makefile, std::string variable)
    : Action{ std::make_shared<Impl>(makefile, std::move(variable)) }
  {
  }

  void operator()(cmMakefile&) const {}

private:
  struct Impl
  {
    Impl(cmMakefile* makefile, std::string variable)
      : Makefile{ makefile }
      , Variable{ std::move(variable) }
    {
    }

    ~Impl()
    {
      this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch(
        this->Variable, cmVariableWatchCommandVariableAccessed);
    }

    cmMakefile* const Makefile;
    std::string const Variable;
  };

  std::shared_ptr<Impl const> Action;
};
} // anonymous namespace

bool cmVariableWatchCommand(std::vector<std::string> const& args,
                            cmExecutionStatus& status)
{
  if (args.empty()) {
    status.SetError("must be called with at least one argument.");
    return false;
  }
  std::string const& variable = args[0];
  std::string command;
  if (args.size() > 1) {
    command = args[1];
  }
  if (variable == "CMAKE_CURRENT_LIST_FILE") {
    status.SetError(cmStrCat("cannot be set on the variable: ", variable));
    return false;
  }

  auto* const data = new cmVariableWatchCallbackData;

  data->InCallback = false;
  data->Command = std::move(command);

  if (!status.GetMakefile().GetCMakeInstance()->GetVariableWatch()->AddWatch(
        variable, cmVariableWatchCommandVariableAccessed, data,
        deleteVariableWatchCallbackData)) {
    deleteVariableWatchCallbackData(data);
    return false;
  }

  status.GetMakefile().AddFinalAction(
    FinalAction{ &status.GetMakefile(), variable });
  return true;
}
