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

#include "cmDependsCompiler.h"

#include <algorithm>
#include <map>
#include <string>
#include <unordered_set>
#include <utility>

#include <cm/optional>
#include <cm/string_view>
#include <cm/vector>
#include <cmext/string_view>

#include "cmsys/FStream.hxx"

#include "cmFileTime.h"
#include "cmGccDepfileReader.h"
#include "cmGccDepfileReaderTypes.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

bool cmDependsCompiler::CheckDependencies(
  const std::string& internalDepFile, const std::vector<std::string>& depFiles,
  cmDepends::DependencyMap& dependencies,
  const std::function<bool(const std::string&)>& isValidPath)
{
  bool status = true;
  bool forceReadDeps = true;

  cmFileTime internalDepFileTime;
  // read cached dependencies stored in internal file
  if (cmSystemTools::FileExists(internalDepFile)) {
    internalDepFileTime.Load(internalDepFile);
    forceReadDeps = false;

    // read current dependencies
    cmsys::ifstream fin(internalDepFile.c_str());
    if (fin) {
      std::string line;
      std::string depender;
      std::vector<std::string>* currentDependencies = nullptr;
      while (std::getline(fin, line)) {
        if (line.empty() || line.front() == '#') {
          continue;
        }
        // Drop carriage return character at the end
        if (line.back() == '\r') {
          line.pop_back();
          if (line.empty()) {
            continue;
          }
        }
        // Check if this a depender line
        if (line.front() != ' ') {
          depender = std::move(line);
          currentDependencies = &dependencies[depender];
          continue;
        }
        // This is a dependee line
        if (currentDependencies) {
          currentDependencies->emplace_back(line.substr(1));
        }
      }
      fin.close();
    }
  }

  // Now, update dependencies map with all new compiler generated
  // dependencies files
  cmFileTime depFileTime;
  for (auto dep = depFiles.begin(); dep != depFiles.end(); dep++) {
    const auto& source = *dep++;
    const auto& target = *dep++;
    const auto& format = *dep++;
    const auto& depFile = *dep;

    if (!cmSystemTools::FileExists(depFile)) {
      continue;
    }

    if (!forceReadDeps) {
      depFileTime.Load(depFile);
    }
    if (forceReadDeps || depFileTime.Compare(internalDepFileTime) >= 0) {
      status = false;
      if (this->Verbose) {
        cmSystemTools::Stdout(cmStrCat("Dependencies file \"", depFile,
                                       "\" is newer than depends file \"",
                                       internalDepFile, "\".\n"));
      }

      std::vector<std::string> depends;
      if (format == "custom"_s) {
        auto deps = cmReadGccDepfile(
          depFile.c_str(), this->LocalGenerator->GetCurrentBinaryDirectory());
        if (!deps) {
          continue;
        }

        for (auto& entry : *deps) {
          depends = std::move(entry.paths);
          if (isValidPath) {
            cm::erase_if(depends, isValidPath);
          }
          // copy depends for each target, except first one, which can be
          // moved
          for (auto index = entry.rules.size() - 1; index > 0; --index) {
            dependencies[entry.rules[index]] = depends;
          }
          dependencies[entry.rules.front()] = std::move(depends);
        }
      } else {
        if (format == "msvc"_s) {
          cmsys::ifstream fin(depFile.c_str());
          if (!fin) {
            continue;
          }

          std::string line;
          if (!isValidPath && !source.empty()) {
            // insert source as first dependency
            depends.push_back(source);
          }
          while (cmSystemTools::GetLineFromStream(fin, line)) {
            depends.emplace_back(std::move(line));
          }
        } else if (format == "gcc"_s) {
          auto deps = cmReadGccDepfile(
            depFile.c_str(), this->LocalGenerator->GetCurrentBinaryDirectory(),
            GccDepfilePrependPaths::Deps);
          if (!deps) {
            continue;
          }

          // dependencies generated by the compiler contains only one target
          depends = std::move(deps->front().paths);
          if (depends.empty()) {
            // unexpectedly empty, ignore it and continue
            continue;
          }

          // depending of the effective format of the dependencies file
          // generated by the compiler, the target can be wrongly identified
          // as a dependency so remove it from the list
          if (depends.front() == target) {
            depends.erase(depends.begin());
          }

          // ensure source file is the first dependency
          if (!source.empty()) {
            if (depends.front() != source) {
              cm::erase(depends, source);
              if (!isValidPath) {
                depends.insert(depends.begin(), source);
              }
            } else if (isValidPath) {
              // remove first dependency because it must not be filtered out
              depends.erase(depends.begin());
            }
          }
        } else {
          // unknown format, ignore it
          continue;
        }

        if (isValidPath) {
          cm::erase_if(depends, isValidPath);
          if (!source.empty()) {
            // insert source as first dependency
            depends.insert(depends.begin(), source);
          }
        }

        dependencies[target] = std::move(depends);
      }
    }
  }

  return status;
}

void cmDependsCompiler::WriteDependencies(
  const cmDepends::DependencyMap& dependencies, std::ostream& makeDepends,
  std::ostream& internalDepends)
{
  // dependencies file consumed by make tool
  const auto& lineContinue = static_cast<cmGlobalUnixMakefileGenerator3*>(
                               this->LocalGenerator->GetGlobalGenerator())
                               ->LineContinueDirective;
  bool supportLongLineDepend = static_cast<cmGlobalUnixMakefileGenerator3*>(
                                 this->LocalGenerator->GetGlobalGenerator())
                                 ->SupportsLongLineDependencies();
  cmDepends::DependencyMap makeDependencies(dependencies);
  std::unordered_set<cm::string_view> phonyTargets;

  // external dependencies file
  for (auto& node : makeDependencies) {
    auto target = this->LocalGenerator->ConvertToMakefilePath(
      this->LocalGenerator->MaybeRelativeToTopBinDir(node.first));
    auto& deps = node.second;
    std::transform(deps.cbegin(), deps.cend(), deps.begin(),
                   [this](const std::string& dep) {
                     return this->LocalGenerator->ConvertToMakefilePath(
                       this->LocalGenerator->MaybeRelativeToTopBinDir(dep));
                   });

    bool first_dep = true;
    if (supportLongLineDepend) {
      makeDepends << target << ": ";
    }
    for (const auto& dep : deps) {
      if (supportLongLineDepend) {
        if (first_dep) {
          first_dep = false;
          makeDepends << dep;
        } else {
          makeDepends << ' ' << lineContinue << "  " << dep;
        }
      } else {
        makeDepends << target << ": " << dep << std::endl;
      }

      phonyTargets.emplace(dep.data(), dep.length());
    }
    makeDepends << std::endl << std::endl;
  }

  // add phony targets
  for (const auto& target : phonyTargets) {
    makeDepends << std::endl << target << ':' << std::endl;
  }

  // internal dependencies file
  for (const auto& node : dependencies) {
    internalDepends << node.first << std::endl;
    for (const auto& dep : node.second) {
      internalDepends << ' ' << dep << std::endl;
    }
    internalDepends << std::endl;
  }
}

void cmDependsCompiler::ClearDependencies(
  const std::vector<std::string>& depFiles)
{
  for (auto dep = depFiles.begin(); dep != depFiles.end(); dep++) {
    dep += 3;
    cmSystemTools::RemoveFile(*dep);
  }
}
