/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst or https://cmake.org/licensing for details.  */
#include "cmLocalXCodeGenerator.h"

#include <memory>
#include <ostream>
#include <utility>

#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalXCodeGenerator.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

class cmGlobalGenerator;

cmLocalXCodeGenerator::cmLocalXCodeGenerator(cmGlobalGenerator* gg,
                                             cmMakefile* mf)
  : cmLocalGenerator(gg, mf)
{
  // the global generator does this, so do not
  // put these flags into the language flags
  this->EmitUniversalBinaryFlags = false;
}

cmLocalXCodeGenerator::~cmLocalXCodeGenerator() = default;

std::string cmLocalXCodeGenerator::GetTargetDirectory(
  cmGeneratorTarget const* target) const
{
  return cmStrCat(target->GetName(), ".dir");
}

void cmLocalXCodeGenerator::AppendFlagEscape(std::string& flags,
                                             std::string const& rawFlag) const
{
  cmGlobalXCodeGenerator const* gg =
    static_cast<cmGlobalXCodeGenerator const*>(this->GlobalGenerator);
  gg->AppendFlag(flags, rawFlag);
}

void cmLocalXCodeGenerator::Generate()
{
  cmLocalGenerator::Generate();

  for (auto const& target : this->GetGeneratorTargets()) {
    target->HasMacOSXRpathInstallNameDir("");
  }
}

void cmLocalXCodeGenerator::AddGeneratorSpecificInstallSetup(std::ostream& os)
{
  // First check if we need to warn about incompatible settings
  for (auto const& target : this->GetGeneratorTargets()) {
    target->HasMacOSXRpathInstallNameDir("");
  }

  // CMakeIOSInstallCombined.cmake needs to know the location of the top of
  // the build directory
  os << "set(CMAKE_BINARY_DIR \"" << this->GetBinaryDirectory() << "\")\n\n";

  if (this->Makefile->PlatformIsAppleEmbedded()) {
    std::string platformName;
    switch (this->Makefile->GetAppleSDKType()) {
      case cmMakefile::AppleSDK::IPhoneOS:
        platformName = "iphoneos";
        break;
      case cmMakefile::AppleSDK::IPhoneSimulator:
        platformName = "iphonesimulator";
        break;
      case cmMakefile::AppleSDK::AppleTVOS:
        platformName = "appletvos";
        break;
      case cmMakefile::AppleSDK::AppleTVSimulator:
        platformName = "appletvsimulator";
        break;
      case cmMakefile::AppleSDK::WatchOS:
        platformName = "watchos";
        break;
      case cmMakefile::AppleSDK::WatchSimulator:
        platformName = "watchsimulator";
        break;
      case cmMakefile::AppleSDK::XROS:
        platformName = "xros";
        break;
      case cmMakefile::AppleSDK::XRSimulator:
        platformName = "xrsimulator";
        break;
      case cmMakefile::AppleSDK::MacOS:
        break;
    }
    if (!platformName.empty()) {
      // The effective platform name is just the platform name with a hyphen
      // prepended. We can get the SUPPORTED_PLATFORMS from the project file
      // at runtime, so we don't need to compute that here.
      /* clang-format off */
      os <<
        "if(NOT PLATFORM_NAME)\n"
        "  if(NOT \"$ENV{PLATFORM_NAME}\" STREQUAL \"\")\n"
        "    set(PLATFORM_NAME \"$ENV{PLATFORM_NAME}\")\n"
        "  endif()\n"
        "  if(NOT PLATFORM_NAME)\n"
        "    set(PLATFORM_NAME " << platformName << ")\n"
        "  endif()\n"
        "endif()\n\n"
        "if(NOT EFFECTIVE_PLATFORM_NAME)\n"
        "  if(NOT \"$ENV{EFFECTIVE_PLATFORM_NAME}\" STREQUAL \"\")\n"
        "    set(EFFECTIVE_PLATFORM_NAME \"$ENV{EFFECTIVE_PLATFORM_NAME}\")\n"
        "  endif()\n"
        "  if(NOT EFFECTIVE_PLATFORM_NAME)\n"
        "    set(EFFECTIVE_PLATFORM_NAME -" << platformName << ")\n"
        "  endif()\n"
        "endif()\n\n";
      /* clang-format off */
    }
  }
}

void cmLocalXCodeGenerator::ComputeObjectFilenames(
  std::map<cmSourceFile const*, std::string>& mapping,
  cmGeneratorTarget const*)
{
  // Count the number of object files with each name. Warn about duplicate
  // names since Xcode names them uniquely automatically with a numeric suffix
  // to avoid exact duplicate file names. Note that Mac file names are not
  // typically case sensitive, hence the LowerCase.
  std::map<std::string, int> counts;
  for (auto& si : mapping) {
    cmSourceFile const* sf = si.first;
    std::string objectName = cmStrCat(
      cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()), ".o");

    std::string objectNameLower = cmSystemTools::LowerCase(objectName);
    counts[objectNameLower] += 1;
    if (2 == counts[objectNameLower]) {
      // TODO: emit warning about duplicate name?
    }
    si.second = objectName;
  }
}

void cmLocalXCodeGenerator::AddXCConfigSources(cmGeneratorTarget* target)
{
  auto xcconfig = target->GetProperty("XCODE_XCCONFIG");
  if (!xcconfig) {
    return;
  }
  auto configs = target->Makefile->GetGeneratorConfigs(
                          cmMakefile::IncludeEmptyConfig);

  for (auto& config : configs) {
    auto file = cmGeneratorExpression::Evaluate(
      *xcconfig,
      this, config);
    if (!file.empty()) {
      target->AddSource(file);
    }
  }
}
