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

#include <utility>

#include "cmsys/Glob.hxx"

#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

class cmExecutionStatus;

cmFindPathCommand::cmFindPathCommand(std::string findCommandName,
                                     cmExecutionStatus& status)
  : cmFindBase(std::move(findCommandName), status)
{
  this->EnvironmentPath = "INCLUDE";
  this->IncludeFileInPath = false;
  this->VariableDocumentation = "Path to a file.";
  this->VariableType = cmStateEnums::PATH;
}
cmFindPathCommand::cmFindPathCommand(cmExecutionStatus& status)
  : cmFindPathCommand("find_path", status)
{
}

// cmFindPathCommand
bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn)
{
  this->CMakePathName = "INCLUDE";

  if (!this->ParseArguments(argsIn)) {
    return false;
  }

  this->DebugMode = this->ComputeIfDebugModeWanted(this->VariableName);

  if (this->AlreadyDefined) {
    this->NormalizeFindResult();
    return true;
  }

  std::string result = this->FindHeader();
  this->StoreFindResult(result);
  return true;
}

std::string cmFindPathCommand::FindHeader()
{
  cmFindBaseDebugState debug(this->FindCommandName, this);
  std::string header;
  if (this->SearchFrameworkFirst || this->SearchFrameworkOnly) {
    header = this->FindFrameworkHeader(debug);
  }
  if (header.empty() && !this->SearchFrameworkOnly) {
    header = this->FindNormalHeader(debug);
  }
  if (header.empty() && this->SearchFrameworkLast) {
    header = this->FindFrameworkHeader(debug);
  }

  return header;
}

std::string cmFindPathCommand::FindHeaderInFramework(
  std::string const& file, std::string const& dir) const
{
  std::string fileName = file;
  std::string frameWorkName;
  std::string::size_type pos = fileName.find('/');
  // if there is a / in the name try to find the header as a framework
  // For example bar/foo.h would look for:
  // bar.framework/Headers/foo.h
  if (pos != std::string::npos) {
    // remove the name from the slash;
    fileName = fileName.substr(pos + 1);
    frameWorkName = file;
    frameWorkName =
      frameWorkName.substr(0, frameWorkName.size() - fileName.size() - 1);
    // if the framework has a path in it then just use the filename
    if (frameWorkName.find('/') != std::string::npos) {
      fileName = file;
      frameWorkName.clear();
    }
    if (!frameWorkName.empty()) {
      std::string fpath = cmStrCat(dir, frameWorkName, ".framework");
      std::string intPath = cmStrCat(fpath, "/Headers/", fileName);
      if (cmSystemTools::FileExists(intPath)) {
        if (this->IncludeFileInPath) {
          return intPath;
        }
        return fpath;
      }
    }
  }
  // if it is not found yet or not a framework header, then do a glob search
  // for all frameworks in the directory: dir/*.framework/Headers/<file>
  std::string glob = cmStrCat(dir, "*.framework/Headers/", file);
  cmsys::Glob globIt;
  globIt.FindFiles(glob);
  std::vector<std::string> files = globIt.GetFiles();
  if (!files.empty()) {
    std::string fheader = cmSystemTools::CollapseFullPath(files[0]);
    if (this->IncludeFileInPath) {
      return fheader;
    }
    fheader.resize(fheader.size() - file.size());
    return fheader;
  }
  return "";
}

std::string cmFindPathCommand::FindNormalHeader(cmFindBaseDebugState& debug)
{
  std::string tryPath;
  for (std::string const& n : this->Names) {
    for (std::string const& sp : this->SearchPaths) {
      tryPath = cmStrCat(sp, n);
      if (cmSystemTools::FileExists(tryPath)) {
        debug.FoundAt(tryPath);
        if (this->IncludeFileInPath) {
          return tryPath;
        }
        return sp;
      }
      debug.FailedAt(tryPath);
    }
  }
  return "";
}

std::string cmFindPathCommand::FindFrameworkHeader(cmFindBaseDebugState& debug)
{
  for (std::string const& n : this->Names) {
    for (std::string const& sp : this->SearchPaths) {
      std::string fwPath = this->FindHeaderInFramework(n, sp);
      fwPath.empty() ? debug.FailedAt(fwPath) : debug.FoundAt(fwPath);
      if (!fwPath.empty()) {
        return fwPath;
      }
    }
  }
  return "";
}

bool cmFindPath(std::vector<std::string> const& args,
                cmExecutionStatus& status)
{
  return cmFindPathCommand(status).InitialPass(args);
}
