/*============================================================================
  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 "cmExportLibraryDependenciesCommand.h"

#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmVersion.h"
#include "cmake.h"

#include <cmsys/auto_ptr.hxx>

bool cmExportLibraryDependenciesCommand::InitialPass(
  std::vector<std::string> const& args, cmExecutionStatus&)
{
  if (this->Disallowed(
        cmPolicies::CMP0033,
        "The export_library_dependencies command should not be called; "
        "see CMP0033.")) {
    return true;
  }
  if (args.size() < 1) {
    this->SetError("called with incorrect number of arguments");
    return false;
  }

  // store the arguments for the final pass
  this->Filename = args[0];
  this->Append = false;
  if (args.size() > 1) {
    if (args[1] == "APPEND") {
      this->Append = true;
    }
  }
  return true;
}

void cmExportLibraryDependenciesCommand::FinalPass()
{
  // export_library_dependencies() shouldn't modify anything
  // ensure this by calling a const method
  this->ConstFinalPass();
}

void cmExportLibraryDependenciesCommand::ConstFinalPass() const
{
  // Use copy-if-different if not appending.
  cmsys::auto_ptr<cmsys::ofstream> foutPtr;
  if (this->Append) {
    cmsys::auto_ptr<cmsys::ofstream> ap(
      new cmsys::ofstream(this->Filename.c_str(), std::ios::app));
    foutPtr = ap;
  } else {
    cmsys::auto_ptr<cmGeneratedFileStream> ap(
      new cmGeneratedFileStream(this->Filename.c_str(), true));
    ap->SetCopyIfDifferent(true);
    foutPtr = ap;
  }
  std::ostream& fout = *foutPtr.get();

  if (!fout) {
    cmSystemTools::Error("Error Writing ", this->Filename.c_str());
    cmSystemTools::ReportLastSystemError("");
    return;
  }

  // Collect dependency information about all library targets built in
  // the project.
  cmake* cm = this->Makefile->GetCMakeInstance();
  cmGlobalGenerator* global = cm->GetGlobalGenerator();
  const std::vector<cmMakefile*>& locals = global->GetMakefiles();
  std::map<std::string, std::string> libDepsOld;
  std::map<std::string, std::string> libDepsNew;
  std::map<std::string, std::string> libTypes;
  for (std::vector<cmMakefile*>::const_iterator i = locals.begin();
       i != locals.end(); ++i) {
    const cmTargets& tgts = (*i)->GetTargets();
    for (cmTargets::const_iterator l = tgts.begin(); l != tgts.end(); ++l) {
      // Get the current target.
      cmTarget const& target = l->second;

      // Skip non-library targets.
      if (target.GetType() < cmState::STATIC_LIBRARY ||
          target.GetType() > cmState::MODULE_LIBRARY) {
        continue;
      }

      // Construct the dependency variable name.
      std::string targetEntry = target.GetName();
      targetEntry += "_LIB_DEPENDS";

      // Construct the dependency variable value with the direct link
      // dependencies.
      std::string valueOld;
      std::string valueNew;
      cmTarget::LinkLibraryVectorType const& libs =
        target.GetOriginalLinkLibraries();
      for (cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
           li != libs.end(); ++li) {
        std::string ltVar = li->first;
        ltVar += "_LINK_TYPE";
        std::string ltValue;
        switch (li->second) {
          case GENERAL_LibraryType:
            valueNew += "general;";
            ltValue = "general";
            break;
          case DEBUG_LibraryType:
            valueNew += "debug;";
            ltValue = "debug";
            break;
          case OPTIMIZED_LibraryType:
            valueNew += "optimized;";
            ltValue = "optimized";
            break;
        }
        std::string lib = li->first;
        if (cmTarget* libtgt = global->FindTarget(lib)) {
          // Handle simple output name changes.  This command is
          // deprecated so we do not support full target name
          // translation (which requires per-configuration info).
          if (const char* outname = libtgt->GetProperty("OUTPUT_NAME")) {
            lib = outname;
          }
        }
        valueOld += lib;
        valueOld += ";";
        valueNew += lib;
        valueNew += ";";

        std::string& ltEntry = libTypes[ltVar];
        if (ltEntry.empty()) {
          ltEntry = ltValue;
        } else if (ltEntry != ltValue) {
          ltEntry = "general";
        }
      }
      libDepsNew[targetEntry] = valueNew;
      libDepsOld[targetEntry] = valueOld;
    }
  }

  // Generate dependency information for both old and new style CMake
  // versions.
  const char* vertest =
    "\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" GREATER 2.4";
  fout << "# Generated by CMake " << cmVersion::GetCMakeVersion() << "\n\n";
  fout << "if(" << vertest << ")\n";
  fout << "  # Information for CMake 2.6 and above.\n";
  for (std::map<std::string, std::string>::const_iterator i =
         libDepsNew.begin();
       i != libDepsNew.end(); ++i) {
    if (!i->second.empty()) {
      fout << "  set(\"" << i->first << "\" \"" << i->second << "\")\n";
    }
  }
  fout << "else()\n";
  fout << "  # Information for CMake 2.4 and lower.\n";
  for (std::map<std::string, std::string>::const_iterator i =
         libDepsOld.begin();
       i != libDepsOld.end(); ++i) {
    if (!i->second.empty()) {
      fout << "  set(\"" << i->first << "\" \"" << i->second << "\")\n";
    }
  }
  for (std::map<std::string, std::string>::const_iterator i = libTypes.begin();
       i != libTypes.end(); ++i) {
    if (i->second != "general") {
      fout << "  set(\"" << i->first << "\" \"" << i->second << "\")\n";
    }
  }
  fout << "endif()\n";
  return;
}
