/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2004-2009 Kitware, Inc.
  Copyright 2004 Alexander Neundorf (neundorf@kde.org)

  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 "cmExtraSublimeTextGenerator.h"
#include "cmake.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLocalGenerator.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmXMLSafe.h"

#include <cmsys/SystemTools.hxx>

/*
Sublime Text 2 Generator
Author: Morné Chamberlain
This generator was initially based off of the CodeBlocks generator.

Some useful URLs:
Homepage:
http://www.sublimetext.com/

File format docs:
http://www.sublimetext.com/docs/2/projects.html
http://sublimetext.info/docs/en/reference/build_systems.html
*/

//----------------------------------------------------------------------------
void cmExtraSublimeTextGenerator
::GetDocumentation(cmDocumentationEntry& entry, const char*) const
{
  entry.Name = this->GetName();
  entry.Brief = "Generates Sublime Text 2 project files.";
}

cmExtraSublimeTextGenerator::cmExtraSublimeTextGenerator()
:cmExternalMakefileProjectGenerator()
{
#if defined(_WIN32)
  this->SupportedGlobalGenerators.push_back("MinGW Makefiles");
  this->SupportedGlobalGenerators.push_back("NMake Makefiles");
// disable until somebody actually tests it:
//  this->SupportedGlobalGenerators.push_back("MSYS Makefiles");
#endif
  this->SupportedGlobalGenerators.push_back("Ninja");
  this->SupportedGlobalGenerators.push_back("Unix Makefiles");
}


void cmExtraSublimeTextGenerator::Generate()
{
  // for each sub project in the project create a sublime text 2 project
  for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator
       it = this->GlobalGenerator->GetProjectMap().begin();
      it!= this->GlobalGenerator->GetProjectMap().end();
      ++it)
    {
    // create a project file
    this->CreateProjectFile(it->second);
    }
}


void cmExtraSublimeTextGenerator::CreateProjectFile(
                                     const std::vector<cmLocalGenerator*>& lgs)
{
  const cmMakefile* mf=lgs[0]->GetMakefile();
  std::string outputDir=mf->GetStartOutputDirectory();
  std::string projectName=mf->GetProjectName();

  const std::string filename =
                     outputDir + "/" + projectName + ".sublime-project";

  this->CreateNewProjectFile(lgs, filename);
}

void cmExtraSublimeTextGenerator
  ::CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
                         const std::string& filename)
{
  const cmMakefile* mf=lgs[0]->GetMakefile();
  cmGeneratedFileStream fout(filename.c_str());
  if(!fout)
    {
    return;
    }

  const std::string &sourceRootRelativeToOutput = cmSystemTools::RelativePath(
                     mf->GetHomeOutputDirectory(),
                     mf->GetHomeDirectory());
  // Write the folder entries to the project file
  fout << "{\n";
  fout << "\t\"folders\":\n\t[\n\t";
  if (!sourceRootRelativeToOutput.empty())
    {
      fout << "\t{\n\t\t\t\"path\": \"" << sourceRootRelativeToOutput << "\"";
      const std::string &outputRelativeToSourceRoot =
        cmSystemTools::RelativePath(mf->GetHomeDirectory(),
                                    mf->GetHomeOutputDirectory());
      if ((!outputRelativeToSourceRoot.empty()) &&
        ((outputRelativeToSourceRoot.length() < 3) ||
          (outputRelativeToSourceRoot.substr(0, 3) != "../")))
        {
        fout << ",\n\t\t\t\"folder_exclude_patterns\": [\"" <<
                outputRelativeToSourceRoot << "\"]";
        }
    }
  else
    {
      fout << "\t{\n\t\t\t\"path\": \"./\"";
    }
  fout << "\n\t\t}";
  // End of the folders section
  fout << "\n\t]";

  // Write the beginning of the build systems section to the project file
  fout << ",\n\t\"build_systems\":\n\t[\n\t";

  // Set of include directories over all targets (sublime text/sublimeclang
  // doesn't currently support these settings per build system, only project
  // wide
  MapSourceFileFlags sourceFileFlags;
  AppendAllTargets(lgs, mf, fout, sourceFileFlags);

  // End of build_systems
  fout << "\n\t]";
  fout << "\n\t}";
}


void cmExtraSublimeTextGenerator::
  AppendAllTargets(const std::vector<cmLocalGenerator*>& lgs,
                   const cmMakefile* mf,
                   cmGeneratedFileStream& fout,
                   MapSourceFileFlags& sourceFileFlags)
{
  std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
  std::string compiler = "";
  if (!lgs.empty())
    {
      this->AppendTarget(fout, "all", lgs[0], 0, make.c_str(), mf,
                         compiler.c_str(), sourceFileFlags, true);
      this->AppendTarget(fout, "clean", lgs[0], 0, make.c_str(), mf,
                         compiler.c_str(), sourceFileFlags, false);
    }

  // add all executable and library targets and some of the GLOBAL
  // and UTILITY targets
  for (std::vector<cmLocalGenerator*>::const_iterator lg=lgs.begin();
       lg!=lgs.end(); lg++)
    {
    cmMakefile* makefile=(*lg)->GetMakefile();
    cmTargets& targets=makefile->GetTargets();
    for (cmTargets::iterator ti = targets.begin();
         ti != targets.end(); ti++)
      {
      switch(ti->second.GetType())
        {
        case cmTarget::GLOBAL_TARGET:
          {
          // Only add the global targets from CMAKE_BINARY_DIR,
          // not from the subdirs
          if (strcmp(makefile->GetStartOutputDirectory(),
                     makefile->GetHomeOutputDirectory())==0)
            {
            this->AppendTarget(fout, ti->first.c_str(), *lg, 0,
                               make.c_str(), makefile, compiler.c_str(),
                               sourceFileFlags, false);
            }
          }
          break;
        case cmTarget::UTILITY:
          // Add all utility targets, except the Nightly/Continuous/
          // Experimental-"sub"targets as e.g. NightlyStart
          if (((ti->first.find("Nightly")==0)   &&(ti->first!="Nightly"))
             || ((ti->first.find("Continuous")==0)&&(ti->first!="Continuous"))
             || ((ti->first.find("Experimental")==0)
                                               && (ti->first!="Experimental")))
            {
            break;
            }

          this->AppendTarget(fout, ti->first.c_str(), *lg, 0,
                             make.c_str(), makefile, compiler.c_str(),
                             sourceFileFlags, false);
          break;
        case cmTarget::EXECUTABLE:
        case cmTarget::STATIC_LIBRARY:
        case cmTarget::SHARED_LIBRARY:
        case cmTarget::MODULE_LIBRARY:
        case cmTarget::OBJECT_LIBRARY:
          {
          this->AppendTarget(fout, ti->first.c_str(), *lg, &ti->second,
                             make.c_str(), makefile, compiler.c_str(),
                             sourceFileFlags, false);
          std::string fastTarget = ti->first;
          fastTarget += "/fast";
          this->AppendTarget(fout, fastTarget.c_str(), *lg, &ti->second,
                             make.c_str(), makefile, compiler.c_str(),
                             sourceFileFlags, false);
          }
          break;
        default:
          break;
        }
      }
    }
}

void cmExtraSublimeTextGenerator::
  AppendTarget(cmGeneratedFileStream& fout,
               const char* targetName,
               cmLocalGenerator* lg,
               cmTarget* target,
               const char* make,
               const cmMakefile* makefile,
               const char*, //compiler
               MapSourceFileFlags& sourceFileFlags,
               bool firstTarget)
{

  if (target != 0)
    {
      cmGeneratorTarget *gtgt = this->GlobalGenerator
                                    ->GetGeneratorTarget(target);
      std::vector<cmSourceFile*> sourceFiles;
      target->GetSourceFiles(sourceFiles);
      std::vector<cmSourceFile*>::const_iterator sourceFilesEnd =
        sourceFiles.end();
      for (std::vector<cmSourceFile*>::const_iterator iter =
        sourceFiles.begin(); iter != sourceFilesEnd; ++iter)
        {
          cmSourceFile* sourceFile = *iter;
          MapSourceFileFlags::iterator sourceFileFlagsIter =
            sourceFileFlags.find(sourceFile->GetFullPath());
          if (sourceFileFlagsIter == sourceFileFlags.end())
            {
            sourceFileFlagsIter =
              sourceFileFlags.insert(MapSourceFileFlags::value_type(
                sourceFile->GetFullPath(), std::vector<std::string>())).first;
            }
          std::vector<std::string>& flags = sourceFileFlagsIter->second;
          std::string flagsString =
            this->ComputeFlagsForObject(*iter, lg, target, gtgt);
          std::string definesString =
            this->ComputeDefines(*iter, lg, target, gtgt);
          flags.clear();
          cmsys::RegularExpression flagRegex;
          // Regular expression to extract compiler flags from a string
          // https://gist.github.com/3944250
          const char* regexString =
            "(^|[ ])-[DIOUWfgs][^= ]+(=\\\"[^\"]+\\\"|=[^\"][^ ]+)?";
          flagRegex.compile(regexString);
          std::string workString = flagsString + " " + definesString;
          while (flagRegex.find(workString))
            {
              std::string::size_type start = flagRegex.start();
              if (workString[start] == ' ')
                {
                  start++;
                }
              flags.push_back(workString.substr(start,
                flagRegex.end() - start));
              if (flagRegex.end() < workString.size())
                {
                workString = workString.substr(flagRegex.end());
                }
                else
                {
                workString = "";
                }
            }
        }
    }

  // Ninja uses ninja.build files (look for a way to get the output file name
  // from cmMakefile or something)
  std::string makefileName;
  if (strcmp(this->GlobalGenerator->GetName(), "Ninja")==0)
    {
      makefileName = "build.ninja";
    }
    else
    {
      makefileName = "Makefile";
    }
  if (!firstTarget)
    {
    fout << ",\n\t";
    }
  fout << "\t{\n\t\t\t\"name\": \"" << makefile->GetProjectName() << " - " <<
          targetName << "\",\n";
  fout << "\t\t\t\"cmd\": [" <<
          this->BuildMakeCommand(make, makefileName.c_str(), targetName) <<
          "],\n";
  fout << "\t\t\t\"working_dir\": \"${project_path}\",\n";
  fout << "\t\t\t\"file_regex\": \"^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$\"\n";
  fout << "\t\t}";
}

// Create the command line for building the given target using the selected
// make
std::string cmExtraSublimeTextGenerator::BuildMakeCommand(
             const std::string& make, const char* makefile, const char* target)
{
  std::string command = "\"";
  command += make + "\"";
  if (strcmp(this->GlobalGenerator->GetName(), "NMake Makefiles")==0)
    {
    std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
    command += ", \"/NOLOGO\", \"/f\", \"";
    command += makefileName + "\"";
    command += ", \"VERBOSE=1\", \"";
    command += target;
    command += "\"";
    }
  else if (strcmp(this->GlobalGenerator->GetName(), "Ninja")==0)
    {
    std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
    command += ", \"-f\", \"";
    command += makefileName + "\"";
    command += ", \"-v\", \"";
    command += target;
    command += "\"";
    }
  else
    {
    std::string makefileName;
    if (strcmp(this->GlobalGenerator->GetName(), "MinGW Makefiles")==0)
      {
        // no escaping of spaces in this case, see
        // http://public.kitware.com/Bug/view.php?id=10014
        makefileName = makefile;
      }
      else
      {
        makefileName = cmSystemTools::ConvertToOutputPath(makefile);
      }
    command += ", \"-f\", \"";
    command += makefileName + "\"";
    command += ", \"VERBOSE=1\", \"";
    command += target;
    command += "\"";
    }
  return command;
}

// TODO: Most of the code is picked up from the Ninja generator, refactor it.
std::string
cmExtraSublimeTextGenerator::ComputeFlagsForObject(cmSourceFile* source,
                                                   cmLocalGenerator* lg,
                                                   cmTarget *target,
                                                   cmGeneratorTarget* gtgt)
{
  std::string flags;

  cmMakefile *makefile = lg->GetMakefile();
  const char* language = source->GetLanguage();
  if (language == NULL)
   {
   language = "C";
   }
  const char* config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
  // Add language-specific flags.
  lg->AddLanguageFlags(flags, language, config);

  lg->AddArchitectureFlags(flags, gtgt, language, config);

  // TODO: Fortran support.
  // // Fortran-specific flags computed for this target.
  // if(*l == "Fortran")
  //   {
  //   this->AddFortranFlags(flags);
  //   }

  // Add shared-library flags if needed.
  lg->AddCMP0018Flags(flags, target, language, config);

  // Add include directory flags.
  {
  std::vector<std::string> includes;
  lg->GetIncludeDirectories(includes, gtgt, language, config);
  std::string includeFlags =
    lg->GetIncludeFlags(includes, gtgt, language, true); // full include paths
  lg->AppendFlags(flags, includeFlags.c_str());
  }

  // Append old-style preprocessor definition flags.
  lg->AppendFlags(flags, makefile->GetDefineFlags());

  // Add target-specific flags.
  lg->AddCompileOptions(flags, target, language, config);

  // Add source file specific flags.
  lg->AppendFlags(flags, source->GetProperty("COMPILE_FLAGS"));

  // TODO: Handle Apple frameworks.

  return flags;
}

// TODO: Refactor with
// void cmMakefileTargetGenerator::WriteTargetLanguageFlags().
std::string
cmExtraSublimeTextGenerator::
ComputeDefines(cmSourceFile *source, cmLocalGenerator* lg, cmTarget *target,
               cmGeneratorTarget*)

{
  std::set<std::string> defines;
  cmMakefile *makefile = lg->GetMakefile();
  const char* language = source->GetLanguage();
  if (language == NULL)
   {
   language = "";
   }
  const char* config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");

  // Add the export symbol definition for shared library objects.
  if(const char* exportMacro = target->GetExportMacro())
    {
    lg->AppendDefines(defines, exportMacro);
    }

  // Add preprocessor definitions for this target and configuration.
  lg->AddCompileDefinitions(defines, target, config);
  lg->AppendDefines(defines, source->GetProperty("COMPILE_DEFINITIONS"));
  {
  std::string defPropName = "COMPILE_DEFINITIONS_";
  defPropName += cmSystemTools::UpperCase(config);
  lg->AppendDefines(defines, source->GetProperty(defPropName.c_str()));
  }

  std::string definesString;
  lg->JoinDefines(defines, definesString, language);

  return definesString;
}
