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

#include <algorithm>
#include <functional>
#include <string>
#include <utility>
#include <vector>

#include <cm/optional>

#include "cmsys/FStream.hxx"

#include "cmGccDepfileReader.h"
#include "cmGccDepfileReaderTypes.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

namespace {
void WriteFilenameGcc(cmsys::ofstream& fout, const std::string& filename)
{
  for (auto c : filename) {
    switch (c) {
      case ' ':
        fout << "\\ ";
        break;
      case '\\':
        fout << "\\\\";
        break;
      default:
        fout << c;
        break;
    }
  }
}

void WriteDepfile(cmDepfileFormat format, cmsys::ofstream& fout,
                  const cmLocalGenerator& lg,
                  const cmGccDepfileContent& content)
{
  std::function<std::string(const std::string&)> formatPath =
    [&lg](const std::string& path) -> std::string {
    return lg.MaybeRelativeToTopBinDir(path);
  };
  if (lg.GetGlobalGenerator()->GetName() == "Xcode") {
    // full paths must be preserved for Xcode compliance
    formatPath = [](const std::string& path) -> std::string { return path; };
  }

  for (auto const& dep : content) {
    bool first = true;
    for (auto const& rule : dep.rules) {
      if (!first) {
        fout << " \\\n  ";
      }
      first = false;
      WriteFilenameGcc(fout, formatPath(rule));
    }
    fout << ':';
    for (auto const& path : dep.paths) {
      fout << " \\\n  ";
      WriteFilenameGcc(fout, formatPath(path));
    }
    fout << '\n';
  }

  if (format == cmDepfileFormat::MakeDepfile) {
    // In this case, phony targets must be added for all dependencies
    fout << "\n";
    for (auto const& dep : content) {
      for (auto const& path : dep.paths) {
        fout << "\n";
        WriteFilenameGcc(fout, formatPath(path));
        fout << ":\n";
      }
    }
  }
}

void WriteMSBuildAdditionalInputs(cmsys::ofstream& fout,
                                  cmLocalGenerator const& lg,
                                  cmGccDepfileContent const& content)
{
  if (content.empty()) {
    return;
  }

  // Write a UTF-8 BOM so MSBuild knows the encoding when reading the file.
  static const char utf8bom[] = { static_cast<char>(0xEF),
                                  static_cast<char>(0xBB),
                                  static_cast<char>(0xBF) };
  fout.write(utf8bom, sizeof(utf8bom));

  // Write the format expected by MSBuild CustomBuild AdditionalInputs.
  const char* sep = "";
  for (const auto& c : content) {
    for (std::string path : c.paths) {
      if (!cmSystemTools::FileIsFullPath(path)) {
        path = cmSystemTools::CollapseFullPath(path,
                                               lg.GetCurrentBinaryDirectory());
      }
      std::replace(path.begin(), path.end(), '/', '\\');
      fout << sep << path;
      sep = ";";
    }
  }
  fout << "\n";
}
}

bool cmTransformDepfile(cmDepfileFormat format, const cmLocalGenerator& lg,
                        const std::string& infile, const std::string& outfile)
{
  cmGccDepfileContent content;
  if (cmSystemTools::FileExists(infile)) {
    auto result =
      cmReadGccDepfile(infile.c_str(), lg.GetCurrentBinaryDirectory());
    if (!result) {
      return false;
    }
    content = *std::move(result);
  } else {
    lg.GetMakefile()->IssueMessage(
      MessageType::WARNING,
      cmStrCat("Expected depfile does not exist.\n  ", infile));
  }

  cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(outfile));
  cmsys::ofstream fout(outfile.c_str());
  if (!fout) {
    return false;
  }
  switch (format) {
    case cmDepfileFormat::GccDepfile:
    case cmDepfileFormat::MakeDepfile:
      WriteDepfile(format, fout, lg, content);
      break;
    case cmDepfileFormat::MSBuildAdditionalInputs:
      WriteMSBuildAdditionalInputs(fout, lg, content);
      break;
  }
  return true;
}
