/* 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 <sstream>
#include <utility>

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

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

static 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;

  cmListFileFunction newLFF;
  cmListFileArgument arg;
  bool processed = false;
  const char* accessString = cmVariableWatch::GetAccessAsString(access_type);
  const char* currentListFile = mf->GetDefinition("CMAKE_CURRENT_LIST_FILE");

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

  std::string stack = makefile->GetProperty("LISTFILE_STACK");
  if (!data->Command.empty()) {
    newLFF.Arguments.clear();
    newLFF.Arguments.emplace_back(variable, cmListFileArgument::Quoted, 9999);
    newLFF.Arguments.emplace_back(accessString, cmListFileArgument::Quoted,
                                  9999);
    newLFF.Arguments.emplace_back(newValue ? newValue : "",
                                  cmListFileArgument::Quoted, 9999);
    newLFF.Arguments.emplace_back(currentListFile, cmListFileArgument::Quoted,
                                  9999);
    newLFF.Arguments.emplace_back(stack, cmListFileArgument::Quoted, 9999);
    newLFF.Name = data->Command;
    newLFF.Line = 9999;
    cmExecutionStatus status(*makefile);
    if (!makefile->ExecuteCommand(newLFF, status)) {
      std::ostringstream error;
      error << "Error in cmake code at\nUnknown:0:\n"
            << "A command failed during the invocation of callback \""
            << data->Command << "\".";
      cmSystemTools::Error(error.str());
      data->InCallback = false;
      return;
    }
    processed = true;
  }
  if (!processed) {
    std::ostringstream msg;
    msg << "Variable \"" << variable << "\" was accessed using "
        << accessString << " with value \"" << (newValue ? newValue : "")
        << "\".";
    makefile->IssueMessage(MessageType::LOG, msg.str());
  }

  data->InCallback = false;
}

static 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:
  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* Makefile;
    std::string Variable;
  };

  std::shared_ptr<Impl const> Action;
};

bool cmVariableWatchCommand::InitialPass(std::vector<std::string> const& args,
                                         cmExecutionStatus&)
{
  if (args.empty()) {
    this->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") {
    std::ostringstream ostr;
    ostr << "cannot be set on the variable: " << variable;
    this->SetError(ostr.str());
    return false;
  }

  cmVariableWatchCallbackData* data = new cmVariableWatchCallbackData;

  data->InCallback = false;
  data->Command = command;

  if (!this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch(
        variable, cmVariableWatchCommandVariableAccessed, data,
        deleteVariableWatchCallbackData)) {
    deleteVariableWatchCallbackData(data);
    return false;
  }

  this->Makefile->AddFinalAction(FinalAction(this->Makefile, variable));
  return true;
}
