/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2015 Geoffrey Viola <geoffrey.viola@asirobots.com>

  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 "cmGhsMultiTargetGenerator.h"
#include "cmGlobalGhsMultiGenerator.h"
#include "cmLocalGhsMultiGenerator.h"
#include "cmMakefile.h"
#include "cmTarget.h"
#include "cmGeneratedFileStream.h"
#include "cmSourceFile.h"
#include <assert.h>
#include <cmAlgorithms.h>

std::string const cmGhsMultiTargetGenerator::DDOption("-dynamic");

cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmGeneratorTarget *target)
  : Target(target->Target)
  , GeneratorTarget(target)
  , LocalGenerator(static_cast<cmLocalGhsMultiGenerator *>(
                     target->GetLocalGenerator()))
  , Makefile(target->Target->GetMakefile())
  , TargetGroup(DetermineIfTargetGroup(target->Target))
  , DynamicDownload(false)
{
  this->RelBuildFilePath = this->GetRelBuildFilePath(target->Target);

  this->RelOutputFileName =
    this->RelBuildFilePath + this->Target->GetName() + ".a";

  this->RelBuildFileName = this->RelBuildFilePath;
  this->RelBuildFileName += this->GetBuildFileName(target->Target);

  std::string absPathToRoot = this->GetAbsPathToRoot(target->Target);
  absPathToRoot = this->AddSlashIfNeededToPath(absPathToRoot);
  this->AbsBuildFilePath = absPathToRoot + this->RelBuildFilePath;
  this->AbsBuildFileName = absPathToRoot + this->RelBuildFileName;
  this->AbsOutputFileName = absPathToRoot + this->RelOutputFileName;
}

cmGhsMultiTargetGenerator::~cmGhsMultiTargetGenerator()
{
  cmDeleteAll(this->FolderBuildStreams);
}

std::string
cmGhsMultiTargetGenerator::GetRelBuildFilePath(const cmTarget *target)
{
  std::string output;
  char const *folderProp = target->GetProperty("FOLDER");
  output = NULL == folderProp ? "" : folderProp;
  cmSystemTools::ConvertToUnixSlashes(output);
  if (!output.empty())
  {
    output += "/";
  }
  output += target->GetName() + "/";
  return output;
}

std::string
cmGhsMultiTargetGenerator::GetAbsPathToRoot(const cmTarget *target)
{
  return target->GetMakefile()->GetHomeOutputDirectory();
}

std::string
cmGhsMultiTargetGenerator::GetAbsBuildFilePath(const cmTarget *target)
{
  std::string output;
  output = cmGhsMultiTargetGenerator::GetAbsPathToRoot(target);
  output = cmGhsMultiTargetGenerator::AddSlashIfNeededToPath(output);
  output += cmGhsMultiTargetGenerator::GetRelBuildFilePath(target);
  return  output;
}

std::string
cmGhsMultiTargetGenerator::GetRelBuildFileName(const cmTarget *target)
{
  std::string output;
  output = cmGhsMultiTargetGenerator::GetRelBuildFilePath(target);
  output = cmGhsMultiTargetGenerator::AddSlashIfNeededToPath(output);
  output += cmGhsMultiTargetGenerator::GetBuildFileName(target);
  return  output;
}

std::string cmGhsMultiTargetGenerator::GetBuildFileName(const cmTarget *target)
{
  std::string output;
  output = target->GetName();
  output += cmGlobalGhsMultiGenerator::FILE_EXTENSION;
  return output;
}

std::string
cmGhsMultiTargetGenerator::AddSlashIfNeededToPath(std::string const &input)
{
  std::string output(input);
  if (!cmHasLiteralSuffix(output, "/"))
    {
    output += "/";
    }
  return output;
}

void cmGhsMultiTargetGenerator::Generate()
{
  const std::vector<cmSourceFile *> objectSources = this->GetSources();
  if (!objectSources.empty() && this->IncludeThisTarget())
    {
    if (!cmSystemTools::FileExists(this->AbsBuildFilePath.c_str()))
      {
      cmSystemTools::MakeDirectory(this->AbsBuildFilePath.c_str());
      }
    cmGlobalGhsMultiGenerator::Open(std::string(""), this->AbsBuildFileName,
                                    &this->FolderBuildStreams);
    cmGlobalGhsMultiGenerator::OpenBuildFileStream(
      this->GetFolderBuildStreams());
    std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
    if (0 == config.length())
      {
      config = "RELEASE";
      }
    const std::string language(
          this->GeneratorTarget->GetLinkerLanguage(config));
    config = cmSystemTools::UpperCase(config);
    this->DynamicDownload = this->DetermineIfDynamicDownload(config, language);
    if (this->DynamicDownload)
      {
      *this->GetFolderBuildStreams() << "#component integrity_dynamic_download"
                                     << std::endl;
      }
    GhsMultiGpj::WriteGpjTag(this->GetGpjTag(), this->GetFolderBuildStreams());
    cmGlobalGhsMultiGenerator::WriteDisclaimer(this->GetFolderBuildStreams());

    bool const notKernel = this->IsNotKernel(config, language);
    this->WriteTypeSpecifics(config, notKernel);
    this->SetCompilerFlags(config, language, notKernel);
    this->WriteCompilerFlags(config, language);
    this->WriteCompilerDefinitions(config, language);
    this->WriteIncludes(config, language);
    if (this->Target->GetType() == cmTarget::EXECUTABLE)
      {
      this->WriteTargetLinkLibraries();
      }
    this->WriteCustomCommands();

    this->WriteSources(objectSources);
    }
}

bool cmGhsMultiTargetGenerator::IncludeThisTarget()
{
  bool output = true;
  char const *excludeFromAll = this->Target->GetProperty("EXCLUDE_FROM_ALL");
  if (NULL != excludeFromAll && '1' == excludeFromAll[0] &&
      '\0' == excludeFromAll[1])
    {
    output = false;
    }
  return output;
}

std::vector<cmSourceFile *> cmGhsMultiTargetGenerator::GetSources() const
{
  std::vector<cmSourceFile *> output;
  std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
  this->Target->GetSourceFiles(output, config);
  return output;
}

GhsMultiGpj::Types cmGhsMultiTargetGenerator::GetGpjTag() const
{
  return cmGhsMultiTargetGenerator::GetGpjTag(this->Target);
}

GhsMultiGpj::Types cmGhsMultiTargetGenerator::GetGpjTag(const cmTarget *target)
{
  GhsMultiGpj::Types output;
  if (cmGhsMultiTargetGenerator::DetermineIfTargetGroup(target))
    {
    output = GhsMultiGpj::INTERGRITY_APPLICATION;
    }
  else if (target->GetType() == cmTarget::STATIC_LIBRARY)
    {
    output = GhsMultiGpj::LIBRARY;
    }
  else
    {
    output = GhsMultiGpj::PROGRAM;
    }
  return output;
}

cmGlobalGhsMultiGenerator*
cmGhsMultiTargetGenerator::GetGlobalGenerator() const
{
  return static_cast<cmGlobalGhsMultiGenerator *>(
    this->LocalGenerator->GetGlobalGenerator());
}

void cmGhsMultiTargetGenerator::WriteTypeSpecifics(const std::string &config,
                                                   bool const notKernel)
{
  std::string outputDir(this->GetOutputDirectory(config));
  std::string outputFilename(this->GetOutputFilename(config));

  if (this->Target->GetType() == cmTarget::STATIC_LIBRARY)
    {
    *this->GetFolderBuildStreams() << "    {optgroup=GhsCommonOptions} -o \""
                                   << outputDir << outputFilename << ".a\""
                                   << std::endl;
    }
  else if (this->Target->GetType() == cmTarget::EXECUTABLE)
    {
    if (notKernel && !this->IsTargetGroup())
      {
      *this->GetFolderBuildStreams() << "    -relprog" << std::endl;
      }
    if (this->IsTargetGroup())
      {
      *this->GetFolderBuildStreams()
          << "    {optgroup=GhsCommonOptions} -o \"" << outputDir
          << outputFilename << ".elf\"" << std::endl;
      *this->GetFolderBuildStreams() << "    :extraOutputFile=\"" << outputDir
                                     << outputFilename << ".elf.ael\""
                                     << std::endl;
      }
    else
      {
      *this->GetFolderBuildStreams() << "    {optgroup=GhsCommonOptions} -o \""
                                     << outputDir << outputFilename << ".as\""
                                     << std::endl;
      }
    }
}

void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const &config,
                                                 const std::string &language,
                                                 bool const notKernel)
{
  std::map<std::string, std::string>::iterator i =
    this->FlagsByLanguage.find(language);
  if (i == this->FlagsByLanguage.end())
    {
    std::string flags;
    const char *lang = language.c_str();

    if (notKernel)
      {
      this->LocalGenerator->AddLanguageFlags(flags, lang, config);
      }
    else
      {
        this->LocalGenerator->AddLanguageFlags(
            flags, lang + std::string("_GHS_KERNEL"), config);
      }
    this->LocalGenerator->AddCMP0018Flags(flags, this->Target, lang, config);
    this->LocalGenerator->AddVisibilityPresetFlags(flags, this->Target, lang);

    // Append old-style preprocessor definition flags.
    if (std::string(" ") != std::string(this->Makefile->GetDefineFlags()))
      {
      this->LocalGenerator->AppendFlags(flags,
                                      this->Makefile->GetDefineFlags());
      }

    // Add target-specific flags.
    this->LocalGenerator->AddCompileOptions(flags, this->Target, lang, config);

    std::map<std::string, std::string>::value_type entry(language, flags);
    i = this->FlagsByLanguage.insert(entry).first;
    }
}

std::string cmGhsMultiTargetGenerator::GetDefines(const std::string &language,
                                                  std::string const &config)
{
  std::map<std::string, std::string>::iterator i =
    this->DefinesByLanguage.find(language);
  if (i == this->DefinesByLanguage.end())
    {
    std::set<std::string> defines;
    const char *lang = language.c_str();
    // Add the export symbol definition for shared library objects.
    if (const char *exportMacro = this->Target->GetExportMacro())
      {
      this->LocalGenerator->AppendDefines(defines, exportMacro);
      }

    // Add preprocessor definitions for this target and configuration.
    this->LocalGenerator->AddCompileDefinitions(defines, this->Target, config,
                                                language);

    std::string definesString;
    this->LocalGenerator->JoinDefines(defines, definesString, lang);

    std::map<std::string, std::string>::value_type entry(language,
                                                          definesString);
    i = this->DefinesByLanguage.insert(entry).first;
    }
  return i->second;
}

void cmGhsMultiTargetGenerator::WriteCompilerFlags(std::string const &,
                                                   const std::string &language)
{
  std::map<std::string, std::string>::iterator flagsByLangI =
      this->FlagsByLanguage.find(language);
  if (flagsByLangI != this->FlagsByLanguage.end())
    {
    if (!flagsByLangI->second.empty())
      {
      *this->GetFolderBuildStreams() << "    " << flagsByLangI->second
        << std::endl;
      }
    }
}

void cmGhsMultiTargetGenerator::WriteCompilerDefinitions(
  const std::string &config, const std::string &language)
{
  std::vector<std::string> compileDefinitions;
  this->GeneratorTarget->GetCompileDefinitions(compileDefinitions,
                                               config, language);
  for (std::vector<std::string>::const_iterator cdI =
         compileDefinitions.begin();
       cdI != compileDefinitions.end(); ++cdI)
    {
    *this->GetFolderBuildStreams() << "    -D" << (*cdI) << std::endl;
    }
}

void cmGhsMultiTargetGenerator::WriteIncludes(const std::string &config,
                                              const std::string &language)
{
  std::vector<std::string> includes =
    this->GeneratorTarget->GetIncludeDirectories(config, language);
  for (std::vector<std::string>::const_iterator includes_i = includes.begin();
       includes_i != includes.end(); ++includes_i)
    {
    *this->GetFolderBuildStreams() << "    -I\"" << *includes_i << "\""
                                   << std::endl;
    }
}

void cmGhsMultiTargetGenerator::WriteTargetLinkLibraries()
{
  // library directories
  cmTargetDependSet tds =
    this->GetGlobalGenerator()->GetTargetDirectDepends(this->GeneratorTarget);
  for (cmTargetDependSet::iterator tdsI = tds.begin(); tdsI != tds.end();
       ++tdsI)
    {
    const cmTarget *tg = (*tdsI)->Target;
    *this->GetFolderBuildStreams() << "    -L\"" << GetAbsBuildFilePath(tg)
                                   << "\"" << std::endl;
    }
  // library targets
  cmTarget::LinkLibraryVectorType llv =
    this->Target->GetOriginalLinkLibraries();
  for (cmTarget::LinkLibraryVectorType::const_iterator llvI = llv.begin();
       llvI != llv.end(); ++llvI)
    {
    std::string libName = llvI->first;
    // if it is a user defined target get the full path to the lib
    cmTarget *tg(GetGlobalGenerator()->FindTarget(libName));
    if (NULL != tg)
      {
      libName = tg->GetName() + ".a";
      }
    *this->GetFolderBuildStreams() << "    -l\"" << libName << "\""
                                   << std::endl;
    }
}

void cmGhsMultiTargetGenerator::WriteCustomCommands()
{
  WriteCustomCommandsHelper(this->Target->GetPreBuildCommands(),
                            cmTarget::PRE_BUILD);
  WriteCustomCommandsHelper(this->Target->GetPostBuildCommands(),
                            cmTarget::POST_BUILD);
}

void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper(
  std::vector<cmCustomCommand> const &commandsSet,
  cmTarget::CustomCommandType const commandType)
{
  for (std::vector<cmCustomCommand>::const_iterator commandsSetI =
         commandsSet.begin();
       commandsSetI != commandsSet.end(); ++commandsSetI)
    {
    cmCustomCommandLines const &commands = commandsSetI->GetCommandLines();
    for (cmCustomCommandLines::const_iterator commandI = commands.begin();
         commandI != commands.end(); ++commandI)
      {
      switch (commandType)
        {
        case cmTarget::PRE_BUILD:
          *this->GetFolderBuildStreams() << "    :preexecShellSafe=";
          break;
        case cmTarget::POST_BUILD:
          *this->GetFolderBuildStreams() << "    :postexecShellSafe=";
          break;
        default:
          assert("Only pre and post are supported");
        }
      cmCustomCommandLine const &command = *commandI;
      for (cmCustomCommandLine::const_iterator commandLineI = command.begin();
           commandLineI != command.end(); ++commandLineI)
        {
        std::string subCommandE =
            this->LocalGenerator->EscapeForShell(*commandLineI, true);
        if (!command.empty())
          {
          *this->GetFolderBuildStreams()
            << (command.begin() == commandLineI ? "'" : " ");
          //Need to double escape backslashes
          cmSystemTools::ReplaceString(subCommandE, "\\", "\\\\");
          }
        *this->GetFolderBuildStreams() << subCommandE;
        }
      if (!command.empty())
        {
        *this->GetFolderBuildStreams() << "'" << std::endl;
        }
      }
    }
}

void cmGhsMultiTargetGenerator::WriteSources(
  std::vector<cmSourceFile *> const &objectSources)
{
  for (std::vector<cmSourceFile *>::const_iterator si = objectSources.begin();
       si != objectSources.end(); ++si)
    {
    std::vector<cmSourceGroup> sourceGroups(this->Makefile->GetSourceGroups());
    char const *sourceFullPath = (*si)->GetFullPath().c_str();
    cmSourceGroup *sourceGroup =
      this->Makefile->FindSourceGroup(sourceFullPath, sourceGroups);
    std::string sgPath(sourceGroup->GetFullName());
    cmSystemTools::ConvertToUnixSlashes(sgPath);
    cmGlobalGhsMultiGenerator::AddFilesUpToPath(
      this->GetFolderBuildStreams(), &this->FolderBuildStreams,
      this->Makefile->GetHomeOutputDirectory(), sgPath,
      GhsMultiGpj::SUBPROJECT, this->RelBuildFilePath);

    std::string fullSourcePath((*si)->GetFullPath());
    if ((*si)->GetExtension() == "int" || (*si)->GetExtension() == "bsp")
      {
      *this->FolderBuildStreams[sgPath] << fullSourcePath << std::endl;
      }
    else
      {
      //WORKAROUND: GHS MULTI needs the path to use backslashes without quotes
      //  to open files in search as of version 6.1.6
      cmsys::SystemTools::ReplaceString(fullSourcePath, "/", "\\");
      *this->FolderBuildStreams[sgPath] << fullSourcePath << std::endl;
      }

    if ("ld" != (*si)->GetExtension() && "int" != (*si)->GetExtension() &&
        "bsp" != (*si)->GetExtension())
      {
      this->WriteObjectLangOverride(this->FolderBuildStreams[sgPath], (*si));

      this->WriteObjectDir(this->FolderBuildStreams[sgPath],
                           this->AbsBuildFilePath + sgPath);
      }
    }
}

void cmGhsMultiTargetGenerator::WriteObjectLangOverride(
  cmGeneratedFileStream *fileStream, cmSourceFile *sourceFile)
{
  const char *rawLangProp = sourceFile->GetProperty("LANGUAGE");
  if (NULL != rawLangProp)
    {
    std::string sourceLangProp(rawLangProp);
    std::string extension(sourceFile->GetExtension());
    if ("CXX" == sourceLangProp && ("c" == extension || "C" == extension))
      {
      *fileStream << "    -dotciscxx" << std::endl;
      }
    }
}

void cmGhsMultiTargetGenerator::WriteObjectDir(
  cmGeneratedFileStream *fileStream, std::string const &dir)
{
  std::string workingDir(dir);
  cmSystemTools::ConvertToUnixSlashes(workingDir);
  if (!workingDir.empty())
    {
    workingDir += "/";
    }
  workingDir += "Objs";
  *fileStream << "    -object_dir=\"" << workingDir << "\"" << std::endl;
}

std::string
cmGhsMultiTargetGenerator::GetOutputDirectory(const std::string &config) const
{
  std::string outputDir(AbsBuildFilePath);

  const char *runtimeOutputProp =
    this->Target->GetProperty("RUNTIME_OUTPUT_DIRECTORY");
  if (NULL != runtimeOutputProp)
    {
    outputDir = runtimeOutputProp;
    }

  std::string configCapped(cmSystemTools::UpperCase(config));
  const char *runtimeOutputSProp =
    this->Target->GetProperty("RUNTIME_OUTPUT_DIRECTORY_" + configCapped);
  if (NULL != runtimeOutputSProp)
    {
    outputDir = runtimeOutputSProp;
    }
  cmSystemTools::ConvertToUnixSlashes(outputDir);

  if (!outputDir.empty())
    {
    outputDir += "/";
    }

  return outputDir;
}

std::string
cmGhsMultiTargetGenerator::GetOutputFilename(const std::string &config) const
{
  std::string outputFilename(this->Target->GetName());

  const char *outputNameProp = this->Target->GetProperty("OUTPUT_NAME");
  if (NULL != outputNameProp)
    {
    outputFilename = outputNameProp;
    }

  std::string configCapped(cmSystemTools::UpperCase(config));
  const char *outputNameSProp =
    this->Target->GetProperty(configCapped + "_OUTPUT_NAME");
  if (NULL != outputNameSProp)
    {
    outputFilename = outputNameSProp;
    }

  return outputFilename;
}

bool cmGhsMultiTargetGenerator::IsNotKernel(std::string const &config,
                                            const std::string &language)
{
  bool output;
  std::vector<std::string> options;
  this->GeneratorTarget->GetCompileOptions(options, config, language);
  output =
    options.end() == std::find(options.begin(), options.end(), "-kernel");
  return output;
}

bool cmGhsMultiTargetGenerator::DetermineIfTargetGroup(const cmTarget *target)
{
  bool output = false;
  std::vector<cmSourceFile *> sources;
  std::string config =
      target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
  target->GetSourceFiles(sources, config);
  for (std::vector<cmSourceFile *>::const_iterator sources_i = sources.begin();
       sources.end() != sources_i; ++sources_i)
    {
    if ("int" == (*sources_i)->GetExtension())
      {
      output = true;
      }
    }
  return output;
}

bool cmGhsMultiTargetGenerator::DetermineIfDynamicDownload(
  std::string const &config, const std::string &language)
{
  std::vector<std::string> options;
  bool output = false;
  this->GeneratorTarget->GetCompileOptions(options, config, language);
  for (std::vector<std::string>::const_iterator options_i = options.begin();
       options_i != options.end(); ++options_i)
    {
    std::string option = *options_i;
    if (this->DDOption == option)
      {
      output = true;
      }
    }
  return output;
}
