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

#include <sstream>

#include "cmMakefile.h"
#include "cmSourceGroup.h"
#include "cmSystemTools.h"

namespace {
const size_t RootIndex = 1;
const size_t FilesWithoutPrefixKeywordIndex = 2;
const size_t FilesWithPrefixKeywordIndex = 4;
const size_t PrefixKeywordIdex = 2;

std::vector<std::string> tokenizePath(const std::string& path)
{
  return cmSystemTools::tokenize(path, "\\/");
}

std::string getFullFilePath(const std::string& currentPath,
                            const std::string& path)
{
  std::string fullPath = path;

  if (!cmSystemTools::FileIsFullPath(path.c_str())) {
    fullPath = currentPath;
    fullPath += "/";
    fullPath += path;
  }

  return cmSystemTools::CollapseFullPath(fullPath);
}

std::set<std::string> getSourceGroupFilesPaths(
  const std::string& currentPath, const std::string& root,
  const std::vector<std::string>& files)
{
  std::set<std::string> ret;
  const std::string::size_type rootLength = root.length();

  for (size_t i = 0; i < files.size(); ++i) {
    const std::string fullPath = getFullFilePath(currentPath, files[i]);

    ret.insert(fullPath.substr(rootLength + 1)); // +1 to also omnit last '/'
  }

  return ret;
}

cmSourceGroup* addSourceGroup(const std::vector<std::string>& tokenizedPath,
                              cmMakefile& makefile)
{
  cmSourceGroup* sg;

  sg = makefile.GetSourceGroup(tokenizedPath);
  if (!sg) {
    makefile.AddSourceGroup(tokenizedPath);
    sg = makefile.GetSourceGroup(tokenizedPath);
    if (!sg) {
      return CM_NULLPTR;
    }
  }

  return sg;
}

bool addFilesToItsSourceGroups(const std::set<std::string>& sgFilesPaths,
                               const std::string& prefix, cmMakefile& makefile,
                               std::string& errorMsg)
{
  cmSourceGroup* sg;

  for (std::set<std::string>::const_iterator it = sgFilesPaths.begin();
       it != sgFilesPaths.end(); ++it) {

    std::vector<std::string> tokenizedPath;
    if (!prefix.empty()) {
      tokenizedPath = tokenizePath(prefix + '/' + *it);
    } else {
      tokenizedPath = tokenizePath(*it);
    }

    if (tokenizedPath.size() > 1) {
      tokenizedPath.pop_back();

      sg = addSourceGroup(tokenizedPath, makefile);

      if (!sg) {
        errorMsg = "Could not create source group for file: " + *it;
        return false;
      }
      const std::string fullPath =
        getFullFilePath(makefile.GetCurrentSourceDirectory(), *it);
      sg->AddGroupFile(fullPath);
    }
  }

  return true;
}
}

class cmExecutionStatus;

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

  if (args[0] == "TREE") {
    std::string error;

    if (!processTree(args, error)) {
      this->SetError(error);
      return false;
    }

    return true;
  }

  std::string delimiter = "\\";
  if (this->Makefile->GetDefinition("SOURCE_GROUP_DELIMITER")) {
    delimiter = this->Makefile->GetDefinition("SOURCE_GROUP_DELIMITER");
  }

  std::vector<std::string> folders =
    cmSystemTools::tokenize(args[0], delimiter);

  cmSourceGroup* sg = CM_NULLPTR;
  sg = this->Makefile->GetSourceGroup(folders);
  if (!sg) {
    this->Makefile->AddSourceGroup(folders);
    sg = this->Makefile->GetSourceGroup(folders);
  }

  if (!sg) {
    this->SetError("Could not create or find source group");
    return false;
  }
  // If only two arguments are given, the pre-1.8 version of the
  // command is being invoked.
  if (args.size() == 2 && args[1] != "FILES") {
    sg->SetGroupRegex(args[1].c_str());
    return true;
  }

  // Process arguments.
  bool doingFiles = false;
  for (unsigned int i = 1; i < args.size(); ++i) {
    if (args[i] == "REGULAR_EXPRESSION") {
      // Next argument must specify the regex.
      if (i + 1 < args.size()) {
        ++i;
        sg->SetGroupRegex(args[i].c_str());
      } else {
        this->SetError("REGULAR_EXPRESSION argument given without a regex.");
        return false;
      }
      doingFiles = false;
    } else if (args[i] == "FILES") {
      // Next arguments will specify files.
      doingFiles = true;
    } else if (doingFiles) {
      // Convert name to full path and add to the group's list.
      std::string src = args[i];
      if (!cmSystemTools::FileIsFullPath(src.c_str())) {
        src = this->Makefile->GetCurrentSourceDirectory();
        src += "/";
        src += args[i];
      }
      src = cmSystemTools::CollapseFullPath(src);
      sg->AddGroupFile(src);
    } else {
      std::ostringstream err;
      err << "Unknown argument \"" << args[i] << "\".  "
          << "Perhaps the FILES keyword is missing.\n";
      this->SetError(err.str());
      return false;
    }
  }

  return true;
}

bool cmSourceGroupCommand::checkTreeArgumentsPreconditions(
  const std::vector<std::string>& args, std::string& errorMsg) const
{
  if (args.size() == 1) {
    errorMsg = "TREE argument given without a root.";
    return false;
  }

  if (args.size() < 3) {
    errorMsg = "Missing FILES arguments.";
    return false;
  }

  if (args[FilesWithoutPrefixKeywordIndex] != "FILES" &&
      args[PrefixKeywordIdex] != "PREFIX") {
    errorMsg = "Unknown argument \"" + args[2] +
      "\". Perhaps the FILES keyword is missing.\n";
    return false;
  }

  if (args[PrefixKeywordIdex] == "PREFIX" &&
      (args.size() < 5 || args[FilesWithPrefixKeywordIndex] != "FILES")) {
    errorMsg = "Missing FILES arguments.";
    return false;
  }

  return true;
}

bool cmSourceGroupCommand::processTree(const std::vector<std::string>& args,
                                       std::string& errorMsg)
{
  if (!checkTreeArgumentsPreconditions(args, errorMsg)) {
    return false;
  }

  const std::string root = cmSystemTools::CollapseFullPath(args[RootIndex]);
  std::string prefix;
  size_t filesBegin = FilesWithoutPrefixKeywordIndex + 1;
  if (args[PrefixKeywordIdex] == "PREFIX") {
    prefix = args[PrefixKeywordIdex + 1];
    filesBegin = FilesWithPrefixKeywordIndex + 1;
  }

  const std::vector<std::string> filesVector(args.begin() + filesBegin,
                                             args.end());

  std::set<std::string> sourceGroupPaths = getSourceGroupFilesPaths(
    this->Makefile->GetCurrentSourceDirectory(), root, filesVector);

  addFilesToItsSourceGroups(sourceGroupPaths, prefix, *(this->Makefile),
                            errorMsg);

  if (!errorMsg.empty()) {
    this->SetError(errorMsg);
    return false;
  }

  return true;
}
