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

#include <memory>
#include <sstream>
#include <utility>

#include "cmsys/FStream.hxx"

#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocationKind.h"
#include "cmSystemTools.h"

cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile(
  std::string input,
  std::unique_ptr<cmCompiledGeneratorExpression> outputFileExpr,
  std::unique_ptr<cmCompiledGeneratorExpression> condition,
  bool inputIsContent, cmPolicies::PolicyStatus policyStatusCMP0070)
  : Input(std::move(input))
  , OutputFileExpr(std::move(outputFileExpr))
  , Condition(std::move(condition))
  , InputIsContent(inputIsContent)
  , PolicyStatusCMP0070(policyStatusCMP0070)
{
}

void cmGeneratorExpressionEvaluationFile::Generate(
  cmLocalGenerator* lg, const std::string& config, const std::string& lang,
  cmCompiledGeneratorExpression* inputExpression,
  std::map<std::string, std::string>& outputFiles, mode_t perm)
{
  std::string rawCondition = this->Condition->GetInput();
  if (!rawCondition.empty()) {
    std::string condResult =
      this->Condition->Evaluate(lg, config, nullptr, nullptr, nullptr, lang);
    if (condResult == "0") {
      return;
    }
    if (condResult != "1") {
      std::ostringstream e;
      e << "Evaluation file condition \"" << rawCondition
        << "\" did "
           "not evaluate to valid content. Got \""
        << condResult << "\".";
      lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
      return;
    }
  }

  std::string outputFileName = this->OutputFileExpr->Evaluate(
    lg, config, nullptr, nullptr, nullptr, lang);
  const std::string& outputContent =
    inputExpression->Evaluate(lg, config, nullptr, nullptr, nullptr, lang);

  if (cmSystemTools::FileIsFullPath(outputFileName)) {
    outputFileName = cmSystemTools::CollapseFullPath(outputFileName);
  } else {
    outputFileName = this->FixRelativePath(outputFileName, PathForOutput, lg);
  }

  auto it = outputFiles.find(outputFileName);

  if (it != outputFiles.end()) {
    if (it->second == outputContent) {
      return;
    }
    std::ostringstream e;
    e << "Evaluation file to be written multiple times with different "
         "content. "
         "This is generally caused by the content evaluating the "
         "configuration type, language, or location of object files:\n "
      << outputFileName;
    lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
    return;
  }

  lg->GetMakefile()->AddCMakeOutputFile(outputFileName);
  this->Files.push_back(outputFileName);
  outputFiles[outputFileName] = outputContent;

  cmGeneratedFileStream fout(outputFileName);
  fout.SetCopyIfDifferent(true);
  fout << outputContent;
  if (fout.Close() && perm) {
    cmSystemTools::SetPermissions(outputFileName.c_str(), perm);
  }
}

void cmGeneratorExpressionEvaluationFile::CreateOutputFile(
  cmLocalGenerator* lg, std::string const& config)
{
  std::vector<std::string> enabledLanguages;
  cmGlobalGenerator* gg = lg->GetGlobalGenerator();
  gg->GetEnabledLanguages(enabledLanguages);

  for (std::string const& le : enabledLanguages) {
    std::string name = this->OutputFileExpr->Evaluate(lg, config, nullptr,
                                                      nullptr, nullptr, le);
    cmSourceFile* sf = lg->GetMakefile()->GetOrCreateSource(
      name, false, cmSourceFileLocationKind::Known);
    // Tell TraceDependencies that the file is not expected to exist
    // on disk yet.  We generate it after that runs.
    sf->SetProperty("GENERATED", "1");

    // Tell the build system generators that there is no build rule
    // to generate the file.
    sf->SetProperty("__CMAKE_GENERATED_BY_CMAKE", "1");

    gg->SetFilenameTargetDepends(
      sf, this->OutputFileExpr->GetSourceSensitiveTargets());
  }
}

void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg)
{
  mode_t perm = 0;
  std::string inputContent;
  if (this->InputIsContent) {
    inputContent = this->Input;
  } else {
    std::string inputFileName = this->Input;
    if (cmSystemTools::FileIsFullPath(inputFileName)) {
      inputFileName = cmSystemTools::CollapseFullPath(inputFileName);
    } else {
      inputFileName = this->FixRelativePath(inputFileName, PathForInput, lg);
    }
    lg->GetMakefile()->AddCMakeDependFile(inputFileName);
    cmSystemTools::GetPermissions(inputFileName.c_str(), perm);
    cmsys::ifstream fin(inputFileName.c_str());
    if (!fin) {
      std::ostringstream e;
      e << "Evaluation file \"" << inputFileName << "\" cannot be read.";
      lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
      return;
    }

    std::string line;
    std::string sep;
    while (cmSystemTools::GetLineFromStream(fin, line)) {
      inputContent += sep + line;
      sep = "\n";
    }
    inputContent += sep;
  }

  cmListFileBacktrace lfbt = this->OutputFileExpr->GetBacktrace();
  cmGeneratorExpression contentGE(lfbt);
  std::unique_ptr<cmCompiledGeneratorExpression> inputExpression =
    contentGE.Parse(inputContent);

  std::map<std::string, std::string> outputFiles;

  std::vector<std::string> allConfigs;
  lg->GetMakefile()->GetConfigurations(allConfigs);

  if (allConfigs.empty()) {
    allConfigs.emplace_back();
  }

  std::vector<std::string> enabledLanguages;
  cmGlobalGenerator* gg = lg->GetGlobalGenerator();
  gg->GetEnabledLanguages(enabledLanguages);

  for (std::string const& le : enabledLanguages) {
    for (std::string const& li : allConfigs) {
      this->Generate(lg, li, le, inputExpression.get(), outputFiles, perm);
      if (cmSystemTools::GetFatalErrorOccured()) {
        return;
      }
    }
  }
}

std::string cmGeneratorExpressionEvaluationFile::FixRelativePath(
  std::string const& relativePath, PathRole role, cmLocalGenerator* lg)
{
  std::string resultPath;
  switch (this->PolicyStatusCMP0070) {
    case cmPolicies::WARN: {
      std::string arg;
      switch (role) {
        case PathForInput:
          arg = "INPUT";
          break;
        case PathForOutput:
          arg = "OUTPUT";
          break;
      }
      std::ostringstream w;
      /* clang-format off */
      w <<
        cmPolicies::GetPolicyWarning(cmPolicies::CMP0070) << "\n"
        "file(GENERATE) given relative " << arg << " path:\n"
        "  " << relativePath << "\n"
        "This is not defined behavior unless CMP0070 is set to NEW.  "
        "For compatibility with older versions of CMake, the previous "
        "undefined behavior will be used."
        ;
      /* clang-format on */
      lg->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
    }
      CM_FALLTHROUGH;
    case cmPolicies::OLD:
      // OLD behavior is to use the relative path unchanged,
      // which ends up being used relative to the working dir.
      resultPath = relativePath;
      break;
    case cmPolicies::REQUIRED_IF_USED:
    case cmPolicies::REQUIRED_ALWAYS:
    case cmPolicies::NEW:
      // NEW behavior is to interpret the relative path with respect
      // to the current source or binary directory.
      switch (role) {
        case PathForInput:
          resultPath = cmSystemTools::CollapseFullPath(
            relativePath, lg->GetCurrentSourceDirectory());
          break;
        case PathForOutput:
          resultPath = cmSystemTools::CollapseFullPath(
            relativePath, lg->GetCurrentBinaryDirectory());
          break;
      }
      break;
  }
  return resultPath;
}
