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

#include "cmAlgorithms.h"
#include "cmCryptoHash.h"
#include "cmFileLockResult.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmUVHandlePtr.h"

// -- Class methods

cmQtAutoGeneratorRcc::cmQtAutoGeneratorRcc()
{
  // Initialize libuv asynchronous iteration request
  UVRequest().init(*UVLoop(), &cmQtAutoGeneratorRcc::UVPollStage, this);
}

cmQtAutoGeneratorRcc::~cmQtAutoGeneratorRcc() = default;

bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
{
  // -- Utility lambdas
  auto InfoGet = [makefile](std::string const& key) {
    return makefile->GetSafeDefinition(key);
  };
  auto InfoGetList =
    [makefile](std::string const& key) -> std::vector<std::string> {
    std::vector<std::string> list;
    cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list);
    return list;
  };
  auto InfoGetConfig = [makefile,
                        this](std::string const& key) -> std::string {
    const char* valueConf = nullptr;
    {
      std::string keyConf = key;
      keyConf += '_';
      keyConf += InfoConfig();
      valueConf = makefile->GetDefinition(keyConf);
    }
    if (valueConf == nullptr) {
      return makefile->GetSafeDefinition(key);
    }
    return std::string(valueConf);
  };
  auto InfoGetConfigList =
    [&InfoGetConfig](std::string const& key) -> std::vector<std::string> {
    std::vector<std::string> list;
    cmSystemTools::ExpandListArgument(InfoGetConfig(key), list);
    return list;
  };

  // -- Read info file
  if (!makefile->ReadListFile(InfoFile())) {
    Log().ErrorFile(GeneratorT::RCC, InfoFile(), "File processing failed");
    return false;
  }

  // - Configurations
  Log().RaiseVerbosity(InfoGet("ARCC_VERBOSITY"));
  MultiConfig_ = makefile->IsOn("ARCC_MULTI_CONFIG");

  // - Directories
  AutogenBuildDir_ = InfoGet("ARCC_BUILD_DIR");
  if (AutogenBuildDir_.empty()) {
    Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Build directory empty");
    return false;
  }

  IncludeDir_ = InfoGetConfig("ARCC_INCLUDE_DIR");
  if (IncludeDir_.empty()) {
    Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Include directory empty");
    return false;
  }

  // - Rcc executable
  RccExecutable_ = InfoGet("ARCC_RCC_EXECUTABLE");
  RccListOptions_ = InfoGetList("ARCC_RCC_LIST_OPTIONS");

  // - Job
  LockFile_ = InfoGet("ARCC_LOCK_FILE");
  QrcFile_ = InfoGet("ARCC_SOURCE");
  QrcFileName_ = cmSystemTools::GetFilenameName(QrcFile_);
  QrcFileDir_ = cmSystemTools::GetFilenamePath(QrcFile_);
  RccPathChecksum_ = InfoGet("ARCC_OUTPUT_CHECKSUM");
  RccFileName_ = InfoGet("ARCC_OUTPUT_NAME");
  Options_ = InfoGetConfigList("ARCC_OPTIONS");
  Inputs_ = InfoGetList("ARCC_INPUTS");

  // - Settings file
  SettingsFile_ = InfoGetConfig("ARCC_SETTINGS_FILE");

  // - Validity checks
  if (LockFile_.empty()) {
    Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Lock file name missing");
    return false;
  }
  if (SettingsFile_.empty()) {
    Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Settings file name missing");
    return false;
  }
  if (AutogenBuildDir_.empty()) {
    Log().ErrorFile(GeneratorT::RCC, InfoFile(),
                    "Autogen build directory missing");
    return false;
  }
  if (RccExecutable_.empty()) {
    Log().ErrorFile(GeneratorT::RCC, InfoFile(), "rcc executable missing");
    return false;
  }
  if (QrcFile_.empty()) {
    Log().ErrorFile(GeneratorT::RCC, InfoFile(), "rcc input file missing");
    return false;
  }
  if (RccFileName_.empty()) {
    Log().ErrorFile(GeneratorT::RCC, InfoFile(), "rcc output file missing");
    return false;
  }

  // Init derived information
  // ------------------------

  RccFilePublic_ = AutogenBuildDir_;
  RccFilePublic_ += '/';
  RccFilePublic_ += RccPathChecksum_;
  RccFilePublic_ += '/';
  RccFilePublic_ += RccFileName_;

  // Compute rcc output file name
  if (IsMultiConfig()) {
    RccFileOutput_ = IncludeDir_;
    RccFileOutput_ += '/';
    RccFileOutput_ += MultiConfigOutput();
  } else {
    RccFileOutput_ = RccFilePublic_;
  }

  return true;
}

bool cmQtAutoGeneratorRcc::Process()
{
  // Run libuv event loop
  UVRequest().send();
  if (uv_run(UVLoop(), UV_RUN_DEFAULT) == 0) {
    if (Error_) {
      return false;
    }
  } else {
    return false;
  }
  return true;
}

void cmQtAutoGeneratorRcc::UVPollStage(uv_async_t* handle)
{
  reinterpret_cast<cmQtAutoGeneratorRcc*>(handle->data)->PollStage();
}

void cmQtAutoGeneratorRcc::PollStage()
{
  switch (Stage_) {
    // -- Initialize
    case StageT::SETTINGS_READ:
      if (SettingsFileRead()) {
        SetStage(StageT::TEST_QRC_RCC_FILES);
      } else {
        SetStage(StageT::FINISH);
      }
      break;

    // -- Change detection
    case StageT::TEST_QRC_RCC_FILES:
      if (TestQrcRccFiles()) {
        SetStage(StageT::GENERATE);
      } else {
        SetStage(StageT::TEST_RESOURCES_READ);
      }
      break;
    case StageT::TEST_RESOURCES_READ:
      if (TestResourcesRead()) {
        SetStage(StageT::TEST_RESOURCES);
      }
      break;
    case StageT::TEST_RESOURCES:
      if (TestResources()) {
        SetStage(StageT::GENERATE);
      } else {
        SetStage(StageT::TEST_INFO_FILE);
      }
      break;
    case StageT::TEST_INFO_FILE:
      TestInfoFile();
      SetStage(StageT::GENERATE_WRAPPER);
      break;

    // -- Generation
    case StageT::GENERATE:
      GenerateParentDir();
      SetStage(StageT::GENERATE_RCC);
      break;
    case StageT::GENERATE_RCC:
      if (GenerateRcc()) {
        SetStage(StageT::GENERATE_WRAPPER);
      }
      break;
    case StageT::GENERATE_WRAPPER:
      GenerateWrapper();
      SetStage(StageT::SETTINGS_WRITE);
      break;

    // -- Finalize
    case StageT::SETTINGS_WRITE:
      SettingsFileWrite();
      SetStage(StageT::FINISH);
      break;
    case StageT::FINISH:
      // Clear all libuv handles
      UVRequest().reset();
      // Set highest END stage manually
      Stage_ = StageT::END;
      break;
    case StageT::END:
      break;
  }
}

void cmQtAutoGeneratorRcc::SetStage(StageT stage)
{
  if (Error_) {
    stage = StageT::FINISH;
  }
  // Only allow to increase the stage
  if (Stage_ < stage) {
    Stage_ = stage;
    UVRequest().send();
  }
}

std::string cmQtAutoGeneratorRcc::MultiConfigOutput() const
{
  static std::string const suffix = "_CMAKE_";
  std::string res;
  res += RccPathChecksum_;
  res += '/';
  res += AppendFilenameSuffix(RccFileName_, suffix);
  return res;
}

bool cmQtAutoGeneratorRcc::SettingsFileRead()
{
  // Compose current settings strings
  {
    cmCryptoHash crypt(cmCryptoHash::AlgoSHA256);
    std::string const sep(" ~~~ ");
    {
      std::string str;
      str += RccExecutable_;
      str += sep;
      str += cmJoin(RccListOptions_, ";");
      str += sep;
      str += QrcFile_;
      str += sep;
      str += RccPathChecksum_;
      str += sep;
      str += RccFileName_;
      str += sep;
      str += cmJoin(Options_, ";");
      str += sep;
      str += cmJoin(Inputs_, ";");
      str += sep;
      SettingsString_ = crypt.HashString(str);
    }
  }

  // Make sure the settings file exists
  if (!FileSys().FileExists(SettingsFile_, true)) {
    // Touch the settings file to make sure it exists
    FileSys().Touch(SettingsFile_, true);
  }

  // Lock the lock file
  {
    // Make sure the lock file exists
    if (!FileSys().FileExists(LockFile_, true)) {
      if (!FileSys().Touch(LockFile_, true)) {
        Log().ErrorFile(GeneratorT::RCC, LockFile_,
                        "Lock file creation failed");
        Error_ = true;
        return false;
      }
    }
    // Lock the lock file
    cmFileLockResult lockResult =
      LockFileLock_.Lock(LockFile_, static_cast<unsigned long>(-1));
    if (!lockResult.IsOk()) {
      Log().ErrorFile(GeneratorT::RCC, LockFile_,
                      "File lock failed: " + lockResult.GetOutputMessage());
      Error_ = true;
      return false;
    }
  }

  // Read old settings
  {
    std::string content;
    if (FileSys().FileRead(content, SettingsFile_)) {
      SettingsChanged_ = (SettingsString_ != SettingsFind(content, "rcc"));
      // In case any setting changed clear the old settings file.
      // This triggers a full rebuild on the next run if the current
      // build is aborted before writing the current settings in the end.
      if (SettingsChanged_) {
        FileSys().FileWrite(GeneratorT::RCC, SettingsFile_, "");
      }
    } else {
      SettingsChanged_ = true;
    }
  }

  return true;
}

void cmQtAutoGeneratorRcc::SettingsFileWrite()
{
  // Only write if any setting changed
  if (SettingsChanged_) {
    if (Log().Verbose()) {
      Log().Info(GeneratorT::RCC,
                 "Writing settings file " + Quoted(SettingsFile_));
    }
    // Write settings file
    std::string content = "rcc:";
    content += SettingsString_;
    content += '\n';
    if (!FileSys().FileWrite(GeneratorT::RCC, SettingsFile_, content)) {
      Log().ErrorFile(GeneratorT::RCC, SettingsFile_,
                      "Settings file writing failed");
      // Remove old settings file to trigger a full rebuild on the next run
      FileSys().FileRemove(SettingsFile_);
      Error_ = true;
    }
  }

  // Unlock the lock file
  LockFileLock_.Release();
}

bool cmQtAutoGeneratorRcc::TestQrcRccFiles()
{
  // Do basic checks if rcc generation is required

  // Test if the rcc output file exists
  if (!FileSys().FileExists(RccFileOutput_)) {
    if (Log().Verbose()) {
      std::string reason = "Generating ";
      reason += Quoted(RccFileOutput_);
      reason += " from its source file ";
      reason += Quoted(QrcFile_);
      reason += " because it doesn't exist";
      Log().Info(GeneratorT::RCC, reason);
    }
    Generate_ = true;
    return Generate_;
  }

  // Test if the settings changed
  if (SettingsChanged_) {
    if (Log().Verbose()) {
      std::string reason = "Generating ";
      reason += Quoted(RccFileOutput_);
      reason += " from ";
      reason += Quoted(QrcFile_);
      reason += " because the RCC settings changed";
      Log().Info(GeneratorT::RCC, reason);
    }
    Generate_ = true;
    return Generate_;
  }

  // Test if the rcc output file is older than the .qrc file
  {
    bool isOlder = false;
    {
      std::string error;
      isOlder = FileSys().FileIsOlderThan(RccFileOutput_, QrcFile_, &error);
      if (!error.empty()) {
        Log().ErrorFile(GeneratorT::RCC, QrcFile_, error);
        Error_ = true;
      }
    }
    if (isOlder) {
      if (Log().Verbose()) {
        std::string reason = "Generating ";
        reason += Quoted(RccFileOutput_);
        reason += " because it is older than ";
        reason += Quoted(QrcFile_);
        Log().Info(GeneratorT::RCC, reason);
      }
      Generate_ = true;
    }
  }

  return Generate_;
}

bool cmQtAutoGeneratorRcc::TestResourcesRead()
{
  if (!Inputs_.empty()) {
    // Inputs are known already
    return true;
  }

  if (!RccListOptions_.empty()) {
    // Start a rcc list process and parse the output
    if (Process_) {
      // Process is running already
      if (Process_->IsFinished()) {
        // Process is finished
        if (!ProcessResult_.error()) {
          // Process success
          std::string parseError;
          if (!RccListParseOutput(ProcessResult_.StdOut, ProcessResult_.StdErr,
                                  Inputs_, parseError)) {
            Log().ErrorFile(GeneratorT::RCC, QrcFile_, parseError);
            Error_ = true;
          }
        } else {
          Log().ErrorFile(GeneratorT::RCC, QrcFile_,
                          ProcessResult_.ErrorMessage);
          Error_ = true;
        }
        // Clean up
        Process_.reset();
        ProcessResult_.reset();
      } else {
        // Process is not finished, yet.
        return false;
      }
    } else {
      // Start a new process
      // rcc prints relative entry paths when started in the directory of the
      // qrc file with a pathless qrc file name argument.
      // This is important because on Windows absolute paths returned by rcc
      // might contain bad multibyte characters when the qrc file path
      // contains non-ASCII pcharacters.
      std::vector<std::string> cmd;
      cmd.push_back(RccExecutable_);
      cmd.insert(cmd.end(), RccListOptions_.begin(), RccListOptions_.end());
      cmd.push_back(QrcFileName_);
      // We're done here if the process fails to start
      return !StartProcess(QrcFileDir_, cmd, false);
    }
  } else {
    // rcc does not support the --list command.
    // Read the qrc file content and parse it.
    std::string qrcContent;
    if (FileSys().FileRead(GeneratorT::RCC, qrcContent, QrcFile_)) {
      RccListParseContent(qrcContent, Inputs_);
    }
  }

  if (!Inputs_.empty()) {
    // Convert relative paths to absolute paths
    RccListConvertFullPath(QrcFileDir_, Inputs_);
  }

  return true;
}

bool cmQtAutoGeneratorRcc::TestResources()
{
  if (Inputs_.empty()) {
    return true;
  }
  {
    std::string error;
    for (std::string const& resFile : Inputs_) {
      // Check if the resource file exists
      if (!FileSys().FileExists(resFile)) {
        error = "Could not find the resource file\n  ";
        error += Quoted(resFile);
        error += '\n';
        Log().ErrorFile(GeneratorT::RCC, QrcFile_, error);
        Error_ = true;
        break;
      }
      // Check if the resource file is newer than the build file
      if (FileSys().FileIsOlderThan(RccFileOutput_, resFile, &error)) {
        if (Log().Verbose()) {
          std::string reason = "Generating ";
          reason += Quoted(RccFileOutput_);
          reason += " from ";
          reason += Quoted(QrcFile_);
          reason += " because it is older than ";
          reason += Quoted(resFile);
          Log().Info(GeneratorT::RCC, reason);
        }
        Generate_ = true;
        break;
      }
      // Print error and break on demand
      if (!error.empty()) {
        Log().ErrorFile(GeneratorT::RCC, QrcFile_, error);
        Error_ = true;
        break;
      }
    }
  }

  return Generate_;
}

void cmQtAutoGeneratorRcc::TestInfoFile()
{
  // Test if the rcc output file is older than the info file
  {
    bool isOlder = false;
    {
      std::string error;
      isOlder = FileSys().FileIsOlderThan(RccFileOutput_, InfoFile(), &error);
      if (!error.empty()) {
        Log().ErrorFile(GeneratorT::RCC, QrcFile_, error);
        Error_ = true;
      }
    }
    if (isOlder) {
      if (Log().Verbose()) {
        std::string reason = "Touching ";
        reason += Quoted(RccFileOutput_);
        reason += " because it is older than ";
        reason += Quoted(InfoFile());
        Log().Info(GeneratorT::RCC, reason);
      }
      // Touch build file
      FileSys().Touch(RccFileOutput_);
      BuildFileChanged_ = true;
    }
  }
}

void cmQtAutoGeneratorRcc::GenerateParentDir()
{
  // Make sure the parent directory exists
  if (!FileSys().MakeParentDirectory(GeneratorT::RCC, RccFileOutput_)) {
    Error_ = true;
  }
}

/**
 * @return True when finished
 */
bool cmQtAutoGeneratorRcc::GenerateRcc()
{
  if (!Generate_) {
    // Nothing to do
    return true;
  }

  if (Process_) {
    // Process is running already
    if (Process_->IsFinished()) {
      // Process is finished
      if (!ProcessResult_.error()) {
        // Rcc process success
        // Print rcc output
        if (!ProcessResult_.StdOut.empty()) {
          Log().Info(GeneratorT::RCC, ProcessResult_.StdOut);
        }
        BuildFileChanged_ = true;
      } else {
        // Rcc process failed
        {
          std::string emsg = "The rcc process failed to compile\n  ";
          emsg += Quoted(QrcFile_);
          emsg += "\ninto\n  ";
          emsg += Quoted(RccFileOutput_);
          if (ProcessResult_.error()) {
            emsg += "\n";
            emsg += ProcessResult_.ErrorMessage;
          }
          Log().ErrorCommand(GeneratorT::RCC, emsg, Process_->Setup().Command,
                             ProcessResult_.StdOut);
        }
        FileSys().FileRemove(RccFileOutput_);
        Error_ = true;
      }
      // Clean up
      Process_.reset();
      ProcessResult_.reset();
    } else {
      // Process is not finished, yet.
      return false;
    }
  } else {
    // Start a rcc process
    std::vector<std::string> cmd;
    cmd.push_back(RccExecutable_);
    cmd.insert(cmd.end(), Options_.begin(), Options_.end());
    cmd.emplace_back("-o");
    cmd.push_back(RccFileOutput_);
    cmd.push_back(QrcFile_);
    // We're done here if the process fails to start
    return !StartProcess(AutogenBuildDir_, cmd, true);
  }

  return true;
}

void cmQtAutoGeneratorRcc::GenerateWrapper()
{
  // Generate a wrapper source file on demand
  if (IsMultiConfig()) {
    // Wrapper file content
    std::string content;
    content += "// This is an autogenerated configuration wrapper file.\n";
    content += "// Changes will be overwritten.\n";
    content += "#include <";
    content += MultiConfigOutput();
    content += ">\n";

    // Write content to file
    if (FileSys().FileDiffers(RccFilePublic_, content)) {
      // Write new wrapper file
      if (Log().Verbose()) {
        Log().Info(GeneratorT::RCC,
                   "Generating RCC wrapper file " + RccFilePublic_);
      }
      if (!FileSys().FileWrite(GeneratorT::RCC, RccFilePublic_, content)) {
        Log().ErrorFile(GeneratorT::RCC, RccFilePublic_,
                        "RCC wrapper file writing failed");
        Error_ = true;
      }
    } else if (BuildFileChanged_) {
      // Just touch the wrapper file
      if (Log().Verbose()) {
        Log().Info(GeneratorT::RCC,
                   "Touching RCC wrapper file " + RccFilePublic_);
      }
      FileSys().Touch(RccFilePublic_);
    }
  }
}

bool cmQtAutoGeneratorRcc::StartProcess(
  std::string const& workingDirectory, std::vector<std::string> const& command,
  bool mergedOutput)
{
  // Log command
  if (Log().Verbose()) {
    std::string msg = "Running command:\n";
    msg += QuotedCommand(command);
    msg += '\n';
    Log().Info(GeneratorT::RCC, msg);
  }

  // Create process handler
  Process_ = cm::make_unique<ReadOnlyProcessT>();
  Process_->setup(&ProcessResult_, mergedOutput, command, workingDirectory);
  // Start process
  if (!Process_->start(UVLoop(), [this] { UVRequest().send(); })) {
    Log().ErrorFile(GeneratorT::RCC, QrcFile_, ProcessResult_.ErrorMessage);
    Error_ = true;
    // Clean up
    Process_.reset();
    ProcessResult_.reset();
    return false;
  }
  return true;
}
