/*=========================================================================

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile$
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "cmQTWrapUICommand.h"

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

  // This command supports source list inputs for compatibility.
  std::vector<std::string> args;
  this->Makefile->ExpandSourceListArguments(argsIn, args, 3);

  // Get the uic and moc executables to run in the custom commands.
  const char* uic_exe =
    this->Makefile->GetRequiredDefinition("QT_UIC_EXECUTABLE");
  const char* moc_exe =
    this->Makefile->GetRequiredDefinition("QT_MOC_EXECUTABLE");

  // Get the variable holding the list of sources.
  std::string const& headerList = args[1];
  std::string const& sourceList = args[2];
  std::string headerListValue =
    this->Makefile->GetSafeDefinition(headerList.c_str());
  std::string sourceListValue =
    this->Makefile->GetSafeDefinition(sourceList.c_str());

  // Create rules for all sources listed.
  for(std::vector<std::string>::iterator j = (args.begin() + 3);
      j != args.end(); ++j)
    {
    cmSourceFile *curr = this->Makefile->GetSource(j->c_str());
    // if we should wrap the class
    if(!(curr && curr->GetPropertyAsBool("WRAP_EXCLUDE")))
      {
      // Compute the name of the files to generate.
      std::string srcName =
        cmSystemTools::GetFilenameWithoutLastExtension(*j);
      std::string hName = this->Makefile->GetCurrentOutputDirectory();
      hName += "/";
      hName += srcName;
      hName += ".h";
      std::string cxxName = this->Makefile->GetCurrentOutputDirectory();
      cxxName += "/";
      cxxName += srcName;
      cxxName += ".cxx";
      std::string mocName = this->Makefile->GetCurrentOutputDirectory();
      mocName += "/moc_";
      mocName += srcName;
      mocName += ".cxx";

      // Compute the name of the ui file from which to generate others.
      std::string uiName;
      if(cmSystemTools::FileIsFullPath(j->c_str()))
        {
        uiName = *j;
        }
      else
        {
        if(curr && curr->GetPropertyAsBool("GENERATED"))
          {
          uiName = this->Makefile->GetCurrentOutputDirectory();
          }
        else
          {
          uiName = this->Makefile->GetCurrentDirectory();
          }
        uiName += "/";
        uiName += *j;
        }

      // create the list of headers
      if(!headerListValue.empty())
        {
        headerListValue += ";";
        }
      headerListValue += hName;

      // create the list of sources
      if(!sourceListValue.empty())
        {
        sourceListValue += ";";
        }
      sourceListValue += cxxName;
      sourceListValue += ";";
      sourceListValue += mocName;

      // set up .ui to .h and .cxx command
      cmCustomCommandLine hCommand;
      hCommand.push_back(uic_exe);
      hCommand.push_back("-o");
      hCommand.push_back(hName);
      hCommand.push_back(uiName);
      cmCustomCommandLines hCommandLines;
      hCommandLines.push_back(hCommand);

      cmCustomCommandLine cxxCommand;
      cxxCommand.push_back(uic_exe);
      cxxCommand.push_back("-impl");
      cxxCommand.push_back(hName);
      cxxCommand.push_back("-o");
      cxxCommand.push_back(cxxName);
      cxxCommand.push_back(uiName);
      cmCustomCommandLines cxxCommandLines;
      cxxCommandLines.push_back(cxxCommand);

      cmCustomCommandLine mocCommand;
      mocCommand.push_back(moc_exe);
      mocCommand.push_back("-o");
      mocCommand.push_back(mocName);
      mocCommand.push_back(hName);
      cmCustomCommandLines mocCommandLines;
      mocCommandLines.push_back(mocCommand);

      std::vector<std::string> depends;
      depends.push_back(uiName);
      const char* no_main_dependency = 0;
      const char* no_comment = 0;
      const char* no_working_dir = 0;
      this->Makefile->AddCustomCommandToOutput(hName.c_str(),
                                               depends,
                                               no_main_dependency,
                                               hCommandLines,
                                               no_comment,
                                               no_working_dir);

      depends.push_back(hName);
      this->Makefile->AddCustomCommandToOutput(cxxName.c_str(),
                                               depends,
                                               no_main_dependency,
                                               cxxCommandLines,
                                               no_comment,
                                               no_working_dir);

      depends.clear();
      depends.push_back(hName);
      this->Makefile->AddCustomCommandToOutput(mocName.c_str(),
                                               depends,
                                               no_main_dependency,
                                               mocCommandLines,
                                               no_comment,
                                               no_working_dir);
      }
    }

  // Store the final list of source files and headers.
  this->Makefile->AddDefinition(sourceList.c_str(),
                                sourceListValue.c_str());
  this->Makefile->AddDefinition(headerList.c_str(),
                                headerListValue.c_str());
  return true;
}
