/*============================================================================
  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 "cmLocalVisualStudioGenerator.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmSystemTools.h"
#include "windows.h"

//----------------------------------------------------------------------------
cmLocalVisualStudioGenerator::cmLocalVisualStudioGenerator()
{
  this->WindowsShell = true;
  this->WindowsVSIDE = true;
}

//----------------------------------------------------------------------------
cmLocalVisualStudioGenerator::~cmLocalVisualStudioGenerator()
{
}

//----------------------------------------------------------------------------
cmsys::auto_ptr<cmCustomCommand>
cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmTarget& target,
                                                   const char* config)
{
  cmsys::auto_ptr<cmCustomCommand> pcc;

  // If an executable exports symbols then VS wants to create an
  // import library but forgets to create the output directory.
  if(target.GetType() != cmTarget::EXECUTABLE) { return pcc; }
  std::string outDir = target.GetDirectory(config, false);
  std::string impDir = target.GetDirectory(config, true);
  if(impDir == outDir) { return pcc; }

  // Add a pre-build event to create the directory.
  cmCustomCommandLine command;
  command.push_back(this->Makefile->GetRequiredDefinition("CMAKE_COMMAND"));
  command.push_back("-E");
  command.push_back("make_directory");
  command.push_back(impDir);
  std::vector<std::string> no_output;
  std::vector<std::string> no_depends;
  cmCustomCommandLines commands;
  commands.push_back(command);
  pcc.reset(new cmCustomCommand(no_output, no_depends, commands, 0, 0));
  pcc->SetEscapeOldStyle(false);
  pcc->SetEscapeAllowMakeVars(true);
  return pcc;
}

//----------------------------------------------------------------------------
bool cmLocalVisualStudioGenerator::SourceFileCompiles(const cmSourceFile* sf)
{
  // Identify the language of the source file.
  if(const char* lang = this->GetSourceFileLanguage(*sf))
    {
    // Check whether this source will actually be compiled.
    return (!sf->GetCustomCommand() &&
            !sf->GetPropertyAsBool("HEADER_FILE_ONLY") &&
            !sf->GetPropertyAsBool("EXTERNAL_OBJECT"));
    }
  else
    {
    // Unknown source file language.  Assume it will not be compiled.
    return false;
    }
}

//----------------------------------------------------------------------------
void cmLocalVisualStudioGenerator::CountObjectNames(
    const std::vector<cmSourceGroup>& groups,
    std::map<cmStdString, int>& counts)
{
  for(unsigned int i = 0; i < groups.size(); ++i)
    {
    cmSourceGroup sg = groups[i];
    std::vector<const cmSourceFile*> const& srcs = sg.GetSourceFiles();
    for(std::vector<const cmSourceFile*>::const_iterator s = srcs.begin();
        s != srcs.end(); ++s)
      {
      const cmSourceFile* sf = *s;
      if(this->SourceFileCompiles(sf))
        {
        std::string objectName = cmSystemTools::LowerCase(
            cmSystemTools::GetFilenameWithoutLastExtension(
              sf->GetFullPath()));
        objectName += ".obj";
        counts[objectName] += 1;
        }
      }
    this->CountObjectNames(sg.GetGroupChildren(), counts);
    }
}

//----------------------------------------------------------------------------
void cmLocalVisualStudioGenerator::InsertNeedObjectNames(
   const std::vector<cmSourceGroup>& groups,
    std::map<cmStdString, int>& count)
{
  for(unsigned int i = 0; i < groups.size(); ++i)
    {
    cmSourceGroup sg = groups[i];
    std::vector<const cmSourceFile*> const& srcs = sg.GetSourceFiles();
    for(std::vector<const cmSourceFile*>::const_iterator s = srcs.begin();
        s != srcs.end(); ++s)
      {
      const cmSourceFile* sf = *s;
      if(this->SourceFileCompiles(sf))
        {
        std::string objectName = cmSystemTools::LowerCase(
           cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()));
        objectName += ".obj";
        if(count[objectName] > 1)
          {
          this->NeedObjectName.insert(sf);
          }
        }
      }
    this->InsertNeedObjectNames(sg.GetGroupChildren(), count);
    }
}


//----------------------------------------------------------------------------
void cmLocalVisualStudioGenerator::ComputeObjectNameRequirements
(std::vector<cmSourceGroup> const& sourceGroups)
{
  // Clear the current set of requirements.
  this->NeedObjectName.clear();

  // Count the number of object files with each name.  Note that
  // windows file names are not case sensitive.
  std::map<cmStdString, int> objectNameCounts;
  this->CountObjectNames(sourceGroups, objectNameCounts);

  // For all source files producing duplicate names we need unique
  // object name computation.
  this->InsertNeedObjectNames(sourceGroups, objectNameCounts);
}

//----------------------------------------------------------------------------
std::string
cmLocalVisualStudioGenerator
::ConstructScript(const cmCustomCommandLines& commandLines,
                  const char* workingDirectory,
                  const char* configName,
                  bool escapeOldStyle,
                  bool escapeAllowMakeVars,
                  const char* newline_text)
{
  // Avoid leading or trailing newlines.
  const char* newline = "";

  // Store the script in a string.
  std::string script;
  if(workingDirectory)
    {
    // Change the working directory.
    script += newline;
    newline = newline_text;
    script += "cd ";
    script += this->Convert(workingDirectory, START_OUTPUT, SHELL);

    // Change the working drive.
    if(workingDirectory[0] && workingDirectory[1] == ':')
      {
      script += newline;
      newline = newline_text;
      script += workingDirectory[0];
      script += workingDirectory[1];
      }
    }
  // for visual studio IDE add extra stuff to the PATH
  // if CMAKE_MSVCIDE_RUN_PATH is set.
  if(this->Makefile->GetDefinition("MSVC_IDE"))
    {
    const char* extraPath =
      this->Makefile->GetDefinition("CMAKE_MSVCIDE_RUN_PATH");
    if(extraPath)
      {
      script += newline;
      newline = newline_text;
      script += "set PATH=";
      script += extraPath;
      script += ";%PATH%";
      }
    }
  // Write each command on a single line.
  for(cmCustomCommandLines::const_iterator cl = commandLines.begin();
      cl != commandLines.end(); ++cl)
    {
    // Start a new line.
    script += newline;
    newline = newline_text;

    // Start with the command name.
    const cmCustomCommandLine& commandLine = *cl;
    std::string commandName = this->GetRealLocation(commandLine[0].c_str(), 
                                                    configName);
    if(!workingDirectory)
      {
      script += this->Convert(commandName.c_str(),START_OUTPUT,SHELL);
      }
    else
      {
      script += this->Convert(commandName.c_str(),NONE,SHELL);
      }

    // Add the arguments.
    for(unsigned int j=1;j < commandLine.size(); ++j)
      {
      script += " ";
      if(escapeOldStyle)
        {
        script += this->EscapeForShellOldStyle(commandLine[j].c_str());
        }
      else
        {
        script += this->EscapeForShell(commandLine[j].c_str(),
                                       escapeAllowMakeVars);
        }
      }
    }
  return script;
}

