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

#include <iterator>

#include <cm3p/json/reader.h>

#include "cmsys/FStream.hxx"

#include "cmQtAutoGen.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"

cmQtAutoGenerator::Logger::Logger()
{
  // Initialize logger
  {
    std::string verbose;
    if (cmSystemTools::GetEnv("VERBOSE", verbose) && !verbose.empty()) {
      unsigned long iVerbose = 0;
      if (cmStrToULong(verbose, &iVerbose)) {
        this->SetVerbosity(static_cast<unsigned int>(iVerbose));
      } else {
        // Non numeric verbosity
        this->SetVerbose(cmIsOn(verbose));
      }
    }
  }
  {
    std::string colorEnv;
    cmSystemTools::GetEnv("COLOR", colorEnv);
    if (!colorEnv.empty()) {
      this->SetColorOutput(cmIsOn(colorEnv));
    } else {
      this->SetColorOutput(true);
    }
  }
}

void cmQtAutoGenerator::Logger::RaiseVerbosity(unsigned int value)
{
  if (this->Verbosity_ < value) {
    this->Verbosity_ = value;
  }
}

void cmQtAutoGenerator::Logger::SetColorOutput(bool value)
{
  this->ColorOutput_ = value;
}

std::string cmQtAutoGenerator::Logger::HeadLine(cm::string_view title)
{
  return cmStrCat(title, '\n', std::string(title.size(), '-'), '\n');
}

void cmQtAutoGenerator::Logger::Info(GenT genType,
                                     cm::string_view message) const
{
  std::string msg = cmStrCat(GeneratorName(genType), ": ", message,
                             cmHasSuffix(message, '\n') ? "" : "\n");
  {
    std::lock_guard<std::mutex> lock(this->Mutex_);
    cmSystemTools::Stdout(msg);
  }
}

void cmQtAutoGenerator::Logger::Warning(GenT genType,
                                        cm::string_view message) const
{
  std::string msg;
  if (message.find('\n') == std::string::npos) {
    // Single line message
    msg = cmStrCat(GeneratorName(genType), " warning: ", message,
                   cmHasSuffix(message, '\n') ? "\n" : "\n\n");
  } else {
    // Multi line message
    msg = cmStrCat(HeadLine(cmStrCat(GeneratorName(genType), " warning")),
                   message, cmHasSuffix(message, '\n') ? "\n" : "\n\n");
  }
  {
    std::lock_guard<std::mutex> lock(this->Mutex_);
    cmSystemTools::Stdout(msg);
  }
}

void cmQtAutoGenerator::Logger::Error(GenT genType,
                                      cm::string_view message) const
{
  std::string msg =
    cmStrCat('\n', HeadLine(cmStrCat(GeneratorName(genType), " error")),
             message, cmHasSuffix(message, '\n') ? "\n" : "\n\n");
  {
    std::lock_guard<std::mutex> lock(this->Mutex_);
    cmSystemTools::Stderr(msg);
  }
}

void cmQtAutoGenerator::Logger::ErrorCommand(
  GenT genType, cm::string_view message,
  std::vector<std::string> const& command, std::string const& output) const
{
  std::string msg = cmStrCat(
    '\n', HeadLine(cmStrCat(GeneratorName(genType), " subprocess error")),
    message, cmHasSuffix(message, '\n') ? "\n" : "\n\n");
  msg += cmStrCat(HeadLine("Command"), QuotedCommand(command), "\n\n");
  msg += cmStrCat(HeadLine("Output"), output,
                  cmHasSuffix(output, '\n') ? "\n" : "\n\n");
  {
    std::lock_guard<std::mutex> lock(this->Mutex_);
    cmSystemTools::Stderr(msg);
  }
}

bool cmQtAutoGenerator::MakeParentDirectory(std::string const& filename)
{
  bool success = true;
  std::string const dirName = cmSystemTools::GetFilenamePath(filename);
  if (!dirName.empty()) {
    success = static_cast<bool>(cmSystemTools::MakeDirectory(dirName));
  }
  return success;
}

bool cmQtAutoGenerator::FileRead(std::string& content,
                                 std::string const& filename,
                                 std::string* error)
{
  content.clear();
  if (!cmSystemTools::FileExists(filename, true)) {
    if (error) {
      *error = "Not a file.";
    }
    return false;
  }

  unsigned long const length = cmSystemTools::FileLength(filename);
  cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));

  // Use lambda to save destructor calls of ifs
  return [&ifs, length, &content, error]() -> bool {
    if (!ifs) {
      if (error) {
        *error = "Opening the file for reading failed.";
      }
      return false;
    }
    content.reserve(length);
    using IsIt = std::istreambuf_iterator<char>;
    content.assign(IsIt{ ifs }, IsIt{});
    if (!ifs) {
      content.clear();
      if (error) {
        *error = "Reading from the file failed.";
      }
      return false;
    }
    return true;
  }();
}

bool cmQtAutoGenerator::FileWrite(std::string const& filename,
                                  std::string const& content,
                                  std::string* error)
{
  // Make sure the parent directory exists
  if (!cmQtAutoGenerator::MakeParentDirectory(filename)) {
    if (error) {
      *error = "Could not create parent directory.";
    }
    return false;
  }
  cmsys::ofstream ofs;
  ofs.open(filename.c_str(),
           (std::ios::out | std::ios::binary | std::ios::trunc));

  // Use lambda to save destructor calls of ofs
  return [&ofs, &content, error]() -> bool {
    if (!ofs) {
      if (error) {
        *error = "Opening file for writing failed.";
      }
      return false;
    }
    ofs << content;
    if (!ofs.good()) {
      if (error) {
        *error = "File writing failed.";
      }
      return false;
    }
    return true;
  }();
}

bool cmQtAutoGenerator::FileDiffers(std::string const& filename,
                                    std::string const& content)
{
  bool differs = true;
  std::string oldContents;
  if (FileRead(oldContents, filename) && (oldContents == content)) {
    differs = false;
  }
  return differs;
}

cmQtAutoGenerator::cmQtAutoGenerator(GenT genType)
  : GenType_(genType)
{
}

cmQtAutoGenerator::~cmQtAutoGenerator() = default;

bool cmQtAutoGenerator::InfoT::Read(std::istream& istr)
{
  try {
    istr >> this->Json_;
  } catch (...) {
    return false;
  }
  return true;
}

bool cmQtAutoGenerator::InfoT::GetJsonArray(std::vector<std::string>& list,
                                            Json::Value const& jval)
{
  Json::ArrayIndex const arraySize = jval.size();
  if (arraySize == 0) {
    return false;
  }

  bool picked = false;
  list.reserve(list.size() + arraySize);
  for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
    Json::Value const& ival = jval[ii];
    if (ival.isString()) {
      list.emplace_back(ival.asString());
      picked = true;
    }
  }
  return picked;
}

bool cmQtAutoGenerator::InfoT::GetJsonArray(
  std::unordered_set<std::string>& list, Json::Value const& jval)
{
  Json::ArrayIndex const arraySize = jval.size();
  if (arraySize == 0) {
    return false;
  }

  bool picked = false;
  list.reserve(list.size() + arraySize);
  for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
    Json::Value const& ival = jval[ii];
    if (ival.isString()) {
      list.emplace(ival.asString());
      picked = true;
    }
  }
  return picked;
}

std::string cmQtAutoGenerator::InfoT::ConfigKey(cm::string_view key) const
{
  return cmStrCat(key, '_', this->Gen_.InfoConfig());
}

bool cmQtAutoGenerator::InfoT::GetString(std::string const& key,
                                         std::string& value,
                                         bool required) const
{
  Json::Value const& jval = this->Json_[key];
  if (!jval.isString()) {
    if (!jval.isNull() || required) {
      return this->LogError(cmStrCat(key, " is not a string."));
    }
  } else {
    value = jval.asString();
    if (value.empty() && required) {
      return this->LogError(cmStrCat(key, " is empty."));
    }
  }
  return true;
}

bool cmQtAutoGenerator::InfoT::GetStringConfig(std::string const& key,
                                               std::string& value,
                                               bool required) const
{
  { // Try config
    std::string const configKey = this->ConfigKey(key);
    Json::Value const& jval = this->Json_[configKey];
    if (!jval.isNull()) {
      if (!jval.isString()) {
        return this->LogError(cmStrCat(configKey, " is not a string."));
      }
      value = jval.asString();
      if (required && value.empty()) {
        return this->LogError(cmStrCat(configKey, " is empty."));
      }
      return true;
    }
  }
  // Try plain
  return this->GetString(key, value, required);
}

bool cmQtAutoGenerator::InfoT::GetBool(std::string const& key, bool& value,
                                       bool required) const
{
  Json::Value const& jval = this->Json_[key];
  if (jval.isBool()) {
    value = jval.asBool();
  } else {
    if (!jval.isNull() || required) {
      return this->LogError(cmStrCat(key, " is not a boolean."));
    }
  }
  return true;
}

bool cmQtAutoGenerator::InfoT::GetUInt(std::string const& key,
                                       unsigned int& value,
                                       bool required) const
{
  Json::Value const& jval = this->Json_[key];
  if (jval.isUInt()) {
    value = jval.asUInt();
  } else {
    if (!jval.isNull() || required) {
      return this->LogError(cmStrCat(key, " is not an unsigned integer."));
    }
  }
  return true;
}

bool cmQtAutoGenerator::InfoT::GetArray(std::string const& key,
                                        std::vector<std::string>& list,
                                        bool required) const
{
  Json::Value const& jval = this->Json_[key];
  if (!jval.isArray()) {
    if (!jval.isNull() || required) {
      return this->LogError(cmStrCat(key, " is not an array."));
    }
  }
  return GetJsonArray(list, jval) || !required;
}

bool cmQtAutoGenerator::InfoT::GetArray(std::string const& key,
                                        std::unordered_set<std::string>& list,
                                        bool required) const
{
  Json::Value const& jval = this->Json_[key];
  if (!jval.isArray()) {
    if (!jval.isNull() || required) {
      return this->LogError(cmStrCat(key, " is not an array."));
    }
  }
  return GetJsonArray(list, jval) || !required;
}

bool cmQtAutoGenerator::InfoT::GetArrayConfig(std::string const& key,
                                              std::vector<std::string>& list,
                                              bool required) const
{
  { // Try config
    std::string const configKey = this->ConfigKey(key);
    Json::Value const& jval = this->Json_[configKey];
    if (!jval.isNull()) {
      if (!jval.isArray()) {
        return this->LogError(cmStrCat(configKey, " is not an array string."));
      }
      if (!GetJsonArray(list, jval) && required) {
        return this->LogError(cmStrCat(configKey, " is empty."));
      }
      return true;
    }
  }
  // Try plain
  return this->GetArray(key, list, required);
}

bool cmQtAutoGenerator::InfoT::LogError(GenT genType,
                                        cm::string_view message) const
{
  this->Gen_.Log().Error(genType,
                         cmStrCat("Info error in info file\n",
                                  Quoted(this->Gen_.InfoFile()), ":\n",
                                  message));
  return false;
}

bool cmQtAutoGenerator::InfoT::LogError(cm::string_view message) const
{
  return this->LogError(this->Gen_.GenType_, message);
}

std::string cmQtAutoGenerator::SettingsFind(cm::string_view content,
                                            cm::string_view key)
{
  cm::string_view res;
  std::string const prefix = cmStrCat(key, ':');
  cm::string_view::size_type pos = content.find(prefix);
  if (pos != cm::string_view::npos) {
    pos += prefix.size();
    if (pos < content.size()) {
      cm::string_view::size_type posE = content.find('\n', pos);
      if ((posE != cm::string_view::npos) && (posE != pos)) {
        res = content.substr(pos, posE - pos);
      }
    }
  }
  return std::string(res);
}

std::string cmQtAutoGenerator::MessagePath(cm::string_view path) const
{
  std::string res;
  if (cmHasPrefix(path, this->ProjectDirs().Source)) {
    res = cmStrCat("SRC:", path.substr(this->ProjectDirs().Source.size()));
  } else if (cmHasPrefix(path, this->ProjectDirs().Binary)) {
    res = cmStrCat("BIN:", path.substr(this->ProjectDirs().Binary.size()));
  } else {
    res = std::string(path);
  }
  return cmQtAutoGen::Quoted(res);
}

bool cmQtAutoGenerator::Run(cm::string_view infoFile, cm::string_view config,
                            cm::string_view executableConfig)
{
  // Info config
  this->InfoConfig_ = std::string(config);
  this->ExecutableConfig_ = std::string(executableConfig);

  // Info file
  this->InfoFile_ = std::string(infoFile);
  this->InfoDir_ = cmSystemTools::GetFilenamePath(this->InfoFile_);

  // Load info file time
  if (!this->InfoFileTime_.Load(this->InfoFile_)) {
    cmSystemTools::Stderr(cmStrCat("AutoGen: The info file ",
                                   Quoted(this->InfoFile_),
                                   " is not readable\n"));
    return false;
  }

  {
    InfoT info(*this);

    // Read info file
    {
      cmsys::ifstream ifs(this->InfoFile_.c_str(),
                          (std::ios::in | std::ios::binary));
      if (!ifs) {
        this->Log().Error(
          this->GenType_,
          cmStrCat("Could not to open info file ", Quoted(this->InfoFile_)));
        return false;
      }
      if (!info.Read(ifs)) {
        this->Log().Error(
          this->GenType_,
          cmStrCat("Could not read info file ", Quoted(this->InfoFile_)));
        return false;
      }
    }

    // -- Read common info settings
    {
      unsigned int verbosity = 0;
      // Info: setup project directories
      if (!info.GetUInt("VERBOSITY", verbosity, false) ||
          !info.GetString("CMAKE_SOURCE_DIR", this->ProjectDirs_.Source,
                          true) ||
          !info.GetString("CMAKE_BINARY_DIR", this->ProjectDirs_.Binary,
                          true) ||
          !info.GetString("CMAKE_CURRENT_SOURCE_DIR",
                          this->ProjectDirs_.CurrentSource, true) ||
          !info.GetString("CMAKE_CURRENT_BINARY_DIR",
                          this->ProjectDirs_.CurrentBinary, true)) {
        return false;
      }
      this->Logger_.RaiseVerbosity(verbosity);
    }

    // -- Call virtual init from info method.
    if (!this->InitFromInfo(info)) {
      return false;
    }
  }

  // Call virtual process method.
  return this->Process();
}
