/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
#include "cmFindPathCommand.h"
#include "cmCacheManager.h"

#include <cmsys/Glob.hxx>

cmFindPathCommand::cmFindPathCommand()
{
  this->EnvironmentPath = "INCLUDE";
  this->IncludeFileInPath = false;
}

void cmFindPathCommand::GenerateDocumentation()
{
  this->cmFindBase::GenerateDocumentation();
  cmSystemTools::ReplaceString(this->GenericDocumentation,
                               "FIND_XXX", "find_path");
  cmSystemTools::ReplaceString(this->GenericDocumentation,
                               "CMAKE_XXX_PATH", "CMAKE_INCLUDE_PATH");
  cmSystemTools::ReplaceString(this->GenericDocumentation,
                               "CMAKE_XXX_MAC_PATH",
                               "CMAKE_FRAMEWORK_PATH");
  cmSystemTools::ReplaceString(this->GenericDocumentation,
                               "CMAKE_SYSTEM_XXX_MAC_PATH",
                               "CMAKE_SYSTEM_FRAMEWORK_PATH");
  cmSystemTools::ReplaceString(this->GenericDocumentation,
                               "XXX_SYSTEM", "INCLUDE");
  cmSystemTools::ReplaceString(this->GenericDocumentation,
                               "CMAKE_SYSTEM_XXX_PATH",
                               "CMAKE_SYSTEM_INCLUDE_PATH");
  cmSystemTools::ReplaceString(this->GenericDocumentation,
                               "SEARCH_XXX_DESC",
                               "directory containing the named file");
  cmSystemTools::ReplaceString(this->GenericDocumentation,
                               "SEARCH_XXX", "file in a directory");
  cmSystemTools::ReplaceString(this->GenericDocumentation,
                               "XXX_SUBDIR", "include");
  cmSystemTools::ReplaceString(
    this->GenericDocumentation,
    "XXX_EXTRA_PREFIX_ENTRY",
    "   <prefix>/include/<arch> if CMAKE_LIBRARY_ARCHITECTURE is set, and\n");
  cmSystemTools::ReplaceString(this->GenericDocumentation,
                               "CMAKE_FIND_ROOT_PATH_MODE_XXX",
                               "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE");
  if(!this->IncludeFileInPath)
    {
    this->GenericDocumentation +=
      "\n"
      "When searching for frameworks, if the file is specified as "
      "A/b.h, then the framework search will look for "
      "A.framework/Headers/b.h. "
      "If that is found the path will be set to the path to the framework. "
      "CMake will convert this to the correct -F option to include the "
      "file. ";
    }
}

// cmFindPathCommand
bool cmFindPathCommand
::InitialPass(std::vector<std::string> const& argsIn, cmExecutionStatus &)
{
  this->VariableDocumentation = "Path to a file.";
  this->CMakePathName = "INCLUDE";
  if(!this->ParseArguments(argsIn))
    {
    return false;
    }
  if(this->AlreadyInCache)
    {
    // If the user specifies the entry on the command line without a
    // type we should add the type and docstring but keep the original
    // value.
    if(this->AlreadyInCacheWithoutMetaInfo)
      {
      this->Makefile->AddCacheDefinition(
        this->VariableName.c_str(), "",
        this->VariableDocumentation.c_str(),
        (this->IncludeFileInPath ?
         cmCacheManager::FILEPATH :cmCacheManager::PATH)
        );
      }
    return true;
    }

  std::string result = this->FindHeader();
  if(result.size() != 0)
    {
    this->Makefile->AddCacheDefinition
      (this->VariableName.c_str(), result.c_str(),
       this->VariableDocumentation.c_str(),
       (this->IncludeFileInPath) ?
       cmCacheManager::FILEPATH :cmCacheManager::PATH);
    return true;
    }
  this->Makefile->AddCacheDefinition
    (this->VariableName.c_str(),
     (this->VariableName + "-NOTFOUND").c_str(),
     this->VariableDocumentation.c_str(),
     (this->IncludeFileInPath) ?
     cmCacheManager::FILEPATH :cmCacheManager::PATH);
  return true;
}

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

std::string
cmFindPathCommand::FindHeaderInFramework(std::string const& file,
                                         std::string const& dir)
{
  cmStdString fileName = file;
  cmStdString frameWorkName;
  cmStdString::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 != fileName.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("/") != frameWorkName.npos)
      {
      fileName = file;
      frameWorkName = "";
      }
    if(frameWorkName.size())
      {
      std::string fpath = dir;
      fpath += frameWorkName;
      fpath += ".framework";
      std::string intPath = fpath;
      intPath += "/Headers/";
      intPath += fileName;
      if(cmSystemTools::FileExists(intPath.c_str()))
        {
        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>
  cmStdString glob = dir;
  glob += "*.framework/Headers/";
  glob += file;
  cmsys::Glob globIt;
  globIt.FindFiles(glob);
  std::vector<std::string> files = globIt.GetFiles();
  if(files.size())
    {
    cmStdString fheader = cmSystemTools::CollapseFullPath(files[0].c_str());
    if(this->IncludeFileInPath)
      {
      return fheader;
      }
    fheader = cmSystemTools::GetFilenamePath(fheader);
    return fheader;
    }
  return "";
}

//----------------------------------------------------------------------------
std::string cmFindPathCommand::FindNormalHeader()
{
  std::string tryPath;
  for(std::vector<std::string>::const_iterator ni = this->Names.begin();
      ni != this->Names.end() ; ++ni)
    {
    for(std::vector<std::string>::const_iterator
          p = this->SearchPaths.begin();
        p != this->SearchPaths.end(); ++p)
      {
      tryPath = *p;
      tryPath += *ni;
      if(cmSystemTools::FileExists(tryPath.c_str()))
        {
        if(this->IncludeFileInPath)
          {
          return tryPath;
          }
        else
          {
          return *p;
          }
        }
      }
    }
  return "";
}

//----------------------------------------------------------------------------
std::string cmFindPathCommand::FindFrameworkHeader()
{
  for(std::vector<std::string>::const_iterator ni = this->Names.begin();
      ni != this->Names.end() ; ++ni)
    {
    for(std::vector<std::string>::const_iterator
          p = this->SearchPaths.begin();
        p != this->SearchPaths.end(); ++p)
      {
      std::string fwPath = this->FindHeaderInFramework(*ni, *p);
      if(!fwPath.empty())
        {
        return fwPath;
        }
      }
    }
  return "";
}
