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

#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"
#include <map>
#include <utility>

#include "cmAlgorithms.h"
#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmSystemTools.h"
#include "cmTarget.h"

class cmExecutionStatus;

/** \class cmDependInformation
 * \brief Store dependency information for a single source file.
 *
 * This structure stores the depend information for a single source file.
 */
class cmDependInformation
{
public:
  /**
   * Construct with dependency generation marked not done; instance
   * not placed in cmMakefile's list.
   */
  cmDependInformation() = default;

  /**
   * The set of files on which this one depends.
   */
  typedef std::set<cmDependInformation*> DependencySetType;
  DependencySetType DependencySet;

  /**
   * This flag indicates whether dependency checking has been
   * performed for this file.
   */
  bool DependDone = false;

  /**
   * If this object corresponds to a cmSourceFile instance, this points
   * to it.
   */
  const cmSourceFile* SourceFile = nullptr;

  /**
   * Full path to this file.
   */
  std::string FullPath;

  /**
   * Full path not including file name.
   */
  std::string PathOnly;

  /**
   * Name used to #include this file.
   */
  std::string IncludeName;

  /**
   * This method adds the dependencies of another file to this one.
   */
  void AddDependencies(cmDependInformation* info)
  {
    if (this != info) {
      this->DependencySet.insert(info);
    }
  }
};

class cmLBDepend
{
public:
  /**
   * Construct the object with verbose turned off.
   */
  cmLBDepend()
  {
    this->Verbose = false;
    this->IncludeFileRegularExpression.compile("^.*$");
    this->ComplainFileRegularExpression.compile("^$");
  }

  /**
   * Destructor.
   */
  ~cmLBDepend() { cmDeleteAll(this->DependInformationMap); }

  /**
   * Set the makefile that is used as a source of classes.
   */
  void SetMakefile(cmMakefile* makefile)
  {
    this->Makefile = makefile;

    // Now extract the include file regular expression from the makefile.
    this->IncludeFileRegularExpression.compile(
      this->Makefile->GetIncludeRegularExpression());
    this->ComplainFileRegularExpression.compile(
      this->Makefile->GetComplainRegularExpression());

    // Now extract any include paths from the targets
    std::set<std::string> uniqueIncludes;
    std::vector<std::string> orderedAndUniqueIncludes;
    cmTargets& targets = this->Makefile->GetTargets();
    for (auto const& target : targets) {
      const char* incDirProp =
        target.second.GetProperty("INCLUDE_DIRECTORIES");
      if (!incDirProp) {
        continue;
      }

      std::string incDirs = cmGeneratorExpression::Preprocess(
        incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions);

      std::vector<std::string> includes;
      cmSystemTools::ExpandListArgument(incDirs, includes);

      for (std::string& path : includes) {
        this->Makefile->ExpandVariablesInString(path);
        if (uniqueIncludes.insert(path).second) {
          orderedAndUniqueIncludes.push_back(path);
        }
      }
    }

    for (std::string const& inc : orderedAndUniqueIncludes) {
      this->AddSearchPath(inc);
    }
  }

  /**
   * Add a directory to the search path for include files.
   */
  void AddSearchPath(const std::string& path)
  {
    this->IncludeDirectories.push_back(path);
  }

  /**
   * Generate dependencies for the file given.  Returns a pointer to
   * the cmDependInformation object for the file.
   */
  const cmDependInformation* FindDependencies(const char* file)
  {
    cmDependInformation* info = this->GetDependInformation(file, nullptr);
    this->GenerateDependInformation(info);
    return info;
  }

protected:
  /**
   * Compute the depend information for this class.
   */

  void DependWalk(cmDependInformation* info)
  {
    cmsys::ifstream fin(info->FullPath.c_str());
    if (!fin) {
      cmSystemTools::Error("error can not open ", info->FullPath.c_str());
      return;
    }

    std::string line;
    while (cmSystemTools::GetLineFromStream(fin, line)) {
      if (cmHasLiteralPrefix(line, "#include")) {
        // if it is an include line then create a string class
        size_t qstart = line.find('\"', 8);
        size_t qend;
        // if a quote is not found look for a <
        if (qstart == std::string::npos) {
          qstart = line.find('<', 8);
          // if a < is not found then move on
          if (qstart == std::string::npos) {
            cmSystemTools::Error("unknown include directive ", line.c_str());
            continue;
          }
          qend = line.find('>', qstart + 1);
        } else {
          qend = line.find('\"', qstart + 1);
        }
        // extract the file being included
        std::string includeFile = line.substr(qstart + 1, qend - qstart - 1);
        // see if the include matches the regular expression
        if (!this->IncludeFileRegularExpression.find(includeFile)) {
          if (this->Verbose) {
            std::string message = "Skipping ";
            message += includeFile;
            message += " for file ";
            message += info->FullPath;
            cmSystemTools::Error(message);
          }
          continue;
        }

        // Add this file and all its dependencies.
        this->AddDependency(info, includeFile.c_str());
        /// add the cxx file if it exists
        std::string cxxFile = includeFile;
        std::string::size_type pos = cxxFile.rfind('.');
        if (pos != std::string::npos) {
          std::string root = cxxFile.substr(0, pos);
          cxxFile = root + ".cxx";
          bool found = false;
          // try jumping to .cxx .cpp and .c in order
          if (cmSystemTools::FileExists(cxxFile)) {
            found = true;
          }
          for (std::string path : this->IncludeDirectories) {
            path = path + "/";
            path = path + cxxFile;
            if (cmSystemTools::FileExists(path)) {
              found = true;
            }
          }
          if (!found) {
            cxxFile = root + ".cpp";
            if (cmSystemTools::FileExists(cxxFile)) {
              found = true;
            }
            for (std::string path : this->IncludeDirectories) {
              path = path + "/";
              path = path + cxxFile;
              if (cmSystemTools::FileExists(path)) {
                found = true;
              }
            }
          }
          if (!found) {
            cxxFile = root + ".c";
            if (cmSystemTools::FileExists(cxxFile)) {
              found = true;
            }
            for (std::string path : this->IncludeDirectories) {
              path = path + "/";
              path = path + cxxFile;
              if (cmSystemTools::FileExists(path)) {
                found = true;
              }
            }
          }
          if (!found) {
            cxxFile = root + ".txx";
            if (cmSystemTools::FileExists(cxxFile)) {
              found = true;
            }
            for (std::string path : this->IncludeDirectories) {
              path = path + "/";
              path = path + cxxFile;
              if (cmSystemTools::FileExists(path)) {
                found = true;
              }
            }
          }
          if (found) {
            this->AddDependency(info, cxxFile.c_str());
          }
        }
      }
    }
  }

  /**
   * Add a dependency.  Possibly walk it for more dependencies.
   */
  void AddDependency(cmDependInformation* info, const char* file)
  {
    cmDependInformation* dependInfo =
      this->GetDependInformation(file, info->PathOnly.c_str());
    this->GenerateDependInformation(dependInfo);
    info->AddDependencies(dependInfo);
  }

  /**
   * Fill in the given object with dependency information.  If the
   * information is already complete, nothing is done.
   */
  void GenerateDependInformation(cmDependInformation* info)
  {
    // If dependencies are already done, stop now.
    if (info->DependDone) {
      return;
    }
    // Make sure we don't visit the same file more than once.
    info->DependDone = true;

    const char* path = info->FullPath.c_str();
    if (!path) {
      cmSystemTools::Error(
        "Attempt to find dependencies for file without path!");
      return;
    }

    bool found = false;

    // If the file exists, use it to find dependency information.
    if (cmSystemTools::FileExists(path, true)) {
      // Use the real file to find its dependencies.
      this->DependWalk(info);
      found = true;
    }

    // See if the cmSourceFile for it has any files specified as
    // dependency hints.
    if (info->SourceFile != nullptr) {

      // Get the cmSourceFile corresponding to this.
      const cmSourceFile& cFile = *(info->SourceFile);
      // See if there are any hints for finding dependencies for the missing
      // file.
      if (!cFile.GetDepends().empty()) {
        // Dependency hints have been given.  Use them to begin the
        // recursion.
        for (std::string const& file : cFile.GetDepends()) {
          this->AddDependency(info, file.c_str());
        }

        // Found dependency information.  We are done.
        found = true;
      }
    }

    if (!found) {
      // Try to find the file amongst the sources
      cmSourceFile* srcFile = this->Makefile->GetSource(
        cmSystemTools::GetFilenameWithoutExtension(path));
      if (srcFile) {
        if (srcFile->GetFullPath() == path) {
          found = true;
        } else {
          // try to guess which include path to use
          for (std::string incpath : this->IncludeDirectories) {
            if (!incpath.empty() && incpath.back() != '/') {
              incpath = incpath + "/";
            }
            incpath = incpath + path;
            if (srcFile->GetFullPath() == incpath) {
              // set the path to the guessed path
              info->FullPath = incpath;
              found = true;
            }
          }
        }
      }
    }

    if (!found) {
      // Couldn't find any dependency information.
      if (this->ComplainFileRegularExpression.find(info->IncludeName)) {
        cmSystemTools::Error("error cannot find dependencies for ", path);
      } else {
        // Destroy the name of the file so that it won't be output as a
        // dependency.
        info->FullPath.clear();
      }
    }
  }

  /**
   * Get an instance of cmDependInformation corresponding to the given file
   * name.
   */
  cmDependInformation* GetDependInformation(const char* file,
                                            const char* extraPath)
  {
    // Get the full path for the file so that lookup is unambiguous.
    std::string fullPath = this->FullPath(file, extraPath);

    // Try to find the file's instance of cmDependInformation.
    DependInformationMapType::const_iterator result =
      this->DependInformationMap.find(fullPath);
    if (result != this->DependInformationMap.end()) {
      // Found an instance, return it.
      return result->second;
    }
    // Didn't find an instance.  Create a new one and save it.
    cmDependInformation* info = new cmDependInformation;
    info->FullPath = fullPath;
    info->PathOnly = cmSystemTools::GetFilenamePath(fullPath);
    info->IncludeName = file;
    this->DependInformationMap[fullPath] = info;
    return info;
  }

  /**
   * Find the full path name for the given file name.
   * This uses the include directories.
   * TODO: Cache path conversions to reduce FileExists calls.
   */
  std::string FullPath(const char* fname, const char* extraPath)
  {
    DirectoryToFileToPathMapType::iterator m;
    if (extraPath) {
      m = this->DirectoryToFileToPathMap.find(extraPath);
    } else {
      m = this->DirectoryToFileToPathMap.find("");
    }

    if (m != this->DirectoryToFileToPathMap.end()) {
      FileToPathMapType& map = m->second;
      FileToPathMapType::iterator p = map.find(fname);
      if (p != map.end()) {
        return p->second;
      }
    }

    if (cmSystemTools::FileExists(fname, true)) {
      std::string fp = cmSystemTools::CollapseFullPath(fname);
      this->DirectoryToFileToPathMap[extraPath ? extraPath : ""][fname] = fp;
      return fp;
    }

    for (std::string path : this->IncludeDirectories) {
      if (!path.empty() && path.back() != '/') {
        path = path + "/";
      }
      path = path + fname;
      if (cmSystemTools::FileExists(path, true) &&
          !cmSystemTools::FileIsDirectory(path)) {
        std::string fp = cmSystemTools::CollapseFullPath(path);
        this->DirectoryToFileToPathMap[extraPath ? extraPath : ""][fname] = fp;
        return fp;
      }
    }

    if (extraPath) {
      std::string path = extraPath;
      if (!path.empty() && path.back() != '/') {
        path = path + "/";
      }
      path = path + fname;
      if (cmSystemTools::FileExists(path, true) &&
          !cmSystemTools::FileIsDirectory(path)) {
        std::string fp = cmSystemTools::CollapseFullPath(path);
        this->DirectoryToFileToPathMap[extraPath][fname] = fp;
        return fp;
      }
    }

    // Couldn't find the file.
    return std::string(fname);
  }

  cmMakefile* Makefile;
  bool Verbose;
  cmsys::RegularExpression IncludeFileRegularExpression;
  cmsys::RegularExpression ComplainFileRegularExpression;
  std::vector<std::string> IncludeDirectories;
  typedef std::map<std::string, std::string> FileToPathMapType;
  typedef std::map<std::string, FileToPathMapType>
    DirectoryToFileToPathMapType;
  typedef std::map<std::string, cmDependInformation*> DependInformationMapType;
  DependInformationMapType DependInformationMap;
  DirectoryToFileToPathMapType DirectoryToFileToPathMap;
};

// cmOutputRequiredFilesCommand
bool cmOutputRequiredFilesCommand::InitialPass(
  std::vector<std::string> const& args, cmExecutionStatus&)
{
  if (args.size() != 2) {
    this->SetError("called with incorrect number of arguments");
    return false;
  }

  // store the arg for final pass
  this->File = args[0];
  this->OutputFile = args[1];

  // compute the list of files
  cmLBDepend md;
  md.SetMakefile(this->Makefile);
  md.AddSearchPath(this->Makefile->GetCurrentSourceDirectory());
  // find the depends for a file
  const cmDependInformation* info = md.FindDependencies(this->File.c_str());
  if (info) {
    // write them out
    FILE* fout = cmsys::SystemTools::Fopen(this->OutputFile, "w");
    if (!fout) {
      std::string err = "Can not open output file: ";
      err += this->OutputFile;
      this->SetError(err);
      return false;
    }
    std::set<cmDependInformation const*> visited;
    this->ListDependencies(info, fout, &visited);
    fclose(fout);
  }

  return true;
}

void cmOutputRequiredFilesCommand::ListDependencies(
  cmDependInformation const* info, FILE* fout,
  std::set<cmDependInformation const*>* visited)
{
  // add info to the visited set
  visited->insert(info);
  // now recurse with info's dependencies
  for (cmDependInformation* d : info->DependencySet) {
    if (visited->find(d) == visited->end()) {
      if (!info->FullPath.empty()) {
        std::string tmp = d->FullPath;
        std::string::size_type pos = tmp.rfind('.');
        if (pos != std::string::npos && (tmp.substr(pos) != ".h")) {
          tmp = tmp.substr(0, pos);
          fprintf(fout, "%s\n", d->FullPath.c_str());
        }
      }
      this->ListDependencies(d, fout, visited);
    }
  }
}
