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

#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 != nullptr) {
      *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 != nullptr) {
        *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 != nullptr) {
        *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 != nullptr) {
      *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 != nullptr) {
        *error = "Opening file for writing failed.";
      }
      return false;
    }
    ofs << content;
    if (!ofs.good()) {
      if (error != nullptr) {
        *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)
{
  // Info config
  this->InfoConfig_ = std::string(config);

  // Info file
  this->InfoFile_ = std::string(infoFile);
  cmSystemTools::CollapseFullPath(this->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();
}
