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

#include "cmsys/FStream.hxx"
#include <sstream>

#include "cmGeneratedFileStream.h"
#include "cmListFileCache.h"
#include "cmSystemTools.h"
#include "cmVersion.h"

bool cmGlobVerificationManager::SaveVerificationScript(const std::string& path)
{
  if (this->Cache.empty()) {
    return true;
  }

  std::string scriptFile = path;
  scriptFile += "/CMakeFiles";
  std::string stampFile = scriptFile;
  cmSystemTools::MakeDirectory(scriptFile);
  scriptFile += "/VerifyGlobs.cmake";
  stampFile += "/cmake.verify_globs";
  cmGeneratedFileStream verifyScriptFile(scriptFile);
  verifyScriptFile.SetCopyIfDifferent(true);
  if (!verifyScriptFile) {
    cmSystemTools::Error("Unable to open verification script file for save. ",
                         scriptFile.c_str());
    cmSystemTools::ReportLastSystemError("");
    return false;
  }

  verifyScriptFile << std::boolalpha;
  verifyScriptFile << "# CMAKE generated file: DO NOT EDIT!\n"
                   << "# Generated by CMake Version "
                   << cmVersion::GetMajorVersion() << "."
                   << cmVersion::GetMinorVersion() << "\n";

  for (auto const& i : this->Cache) {
    CacheEntryKey k = std::get<0>(i);
    CacheEntryValue v = std::get<1>(i);

    if (!v.Initialized) {
      continue;
    }

    verifyScriptFile << "\n";

    for (auto const& bt : v.Backtraces) {
      verifyScriptFile << "# " << std::get<0>(bt);
      std::get<1>(bt).PrintTitle(verifyScriptFile);
      verifyScriptFile << "\n";
    }

    k.PrintGlobCommand(verifyScriptFile, "NEW_GLOB");
    verifyScriptFile << "\n";

    verifyScriptFile << "set(OLD_GLOB\n";
    for (const std::string& file : v.Files) {
      verifyScriptFile << "  \"" << file << "\"\n";
    }
    verifyScriptFile << "  )\n";

    verifyScriptFile << "if(NOT \"${NEW_GLOB}\" STREQUAL \"${OLD_GLOB}\")\n"
                     << "  message(\"-- GLOB mismatch!\")\n"
                     << "  file(TOUCH_NOCREATE \"" << stampFile << "\")\n"
                     << "endif()\n";
  }
  verifyScriptFile.Close();

  cmsys::ofstream verifyStampFile(stampFile.c_str());
  if (!verifyStampFile) {
    cmSystemTools::Error("Unable to open verification stamp file for write. ",
                         stampFile.c_str());
    return false;
  }
  verifyStampFile << "# This file is generated by CMake for checking of the "
                     "VerifyGlobs.cmake file\n";
  this->VerifyScript = scriptFile;
  this->VerifyStamp = stampFile;
  return true;
}

bool cmGlobVerificationManager::DoWriteVerifyTarget() const
{
  return !this->VerifyScript.empty() && !this->VerifyStamp.empty();
}

bool cmGlobVerificationManager::CacheEntryKey::operator<(
  const CacheEntryKey& r) const
{
  if (this->Recurse < r.Recurse) {
    return true;
  }
  if (this->Recurse > r.Recurse) {
    return false;
  }
  if (this->ListDirectories < r.ListDirectories) {
    return true;
  }
  if (this->ListDirectories > r.ListDirectories) {
    return false;
  }
  if (this->FollowSymlinks < r.FollowSymlinks) {
    return true;
  }
  if (this->FollowSymlinks > r.FollowSymlinks) {
    return false;
  }
  if (this->Relative < r.Relative) {
    return true;
  }
  if (this->Relative > r.Relative) {
    return false;
  }
  if (this->Expression < r.Expression) {
    return true;
  }
  if (this->Expression > r.Expression) {
    return false;
  }
  return false;
}

void cmGlobVerificationManager::CacheEntryKey::PrintGlobCommand(
  std::ostream& out, const std::string& cmdVar)
{
  out << "file(GLOB" << (this->Recurse ? "_RECURSE " : " ");
  out << cmdVar << " ";
  if (this->Recurse && this->FollowSymlinks) {
    out << "FOLLOW_SYMLINKS ";
  }
  out << "LIST_DIRECTORIES " << this->ListDirectories << " ";
  if (!this->Relative.empty()) {
    out << "RELATIVE \"" << this->Relative << "\" ";
  }
  out << "\"" << this->Expression << "\")";
}

void cmGlobVerificationManager::AddCacheEntry(
  const bool recurse, const bool listDirectories, const bool followSymlinks,
  const std::string& relative, const std::string& expression,
  const std::vector<std::string>& files, const std::string& variable,
  const cmListFileBacktrace& backtrace)
{
  CacheEntryKey key = CacheEntryKey(recurse, listDirectories, followSymlinks,
                                    relative, expression);
  CacheEntryValue& value = this->Cache[key];
  if (!value.Initialized) {
    value.Files = files;
    value.Initialized = true;
    value.Backtraces.emplace_back(variable, backtrace);
  } else if (value.Initialized && value.Files != files) {
    std::ostringstream message;
    message << std::boolalpha;
    message << "The glob expression\n";
    key.PrintGlobCommand(message, variable);
    backtrace.PrintTitle(message);
    message << "\nwas already present in the glob cache but the directory\n"
               "contents have changed during the configuration run.\n";
    message << "Matching glob expressions:";
    for (auto const& bt : value.Backtraces) {
      message << "\n  " << std::get<0>(bt);
      std::get<1>(bt).PrintTitle(message);
    }
    cmSystemTools::Error(message.str());
  } else {
    value.Backtraces.emplace_back(variable, backtrace);
  }
}

void cmGlobVerificationManager::Reset()
{
  this->Cache.clear();
  this->VerifyScript.clear();
  this->VerifyStamp.clear();
}
