/* 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 <iterator>
#include <map>
#include <memory>
#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 != nullptr) {
          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) {
            auto& rule_deps = dependencies[entry.rules[index]];
            rule_deps.insert(rule_deps.end(), depends.cbegin(),
                             depends.cend());
          }
          auto& rule_deps = dependencies[entry.rules.front()];
          std::move(depends.cbegin(), depends.cend(),
                    std::back_inserter(rule_deps));
        }
      } else {
        if (format == "msvc"_s) {
          cmsys::ifstream fin(depFile.c_str());
          if (!fin) {
            continue;
          }

          std::string line;
          if (!isValidPath) {
            // 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 (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);
          // 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);
  }
}
