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

#include <cstring>
#include <utility>
#include <vector>

#include <cmext/string_view>

#include "cmGlobalGenerator.h"
#include "cmGlobalVisualStudioGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator(
  cmake* cm, std::string const& name)
  : cmGlobalVisualStudio10Generator(cm, name)
{
}

void cmGlobalVisualStudio11Generator::EnableLanguage(
  std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
{
  for (std::string const& it : lang) {
    if (it == "ASM_MARMASM"_s) {
      this->MarmasmEnabled = true;
    }
  }
  this->AddPlatformDefinitions(mf);
  cmGlobalVisualStudio10Generator::EnableLanguage(lang, mf, optional);
}

bool cmGlobalVisualStudio11Generator::InitializeWindowsPhone(cmMakefile* mf)
{
  if (!this->SelectWindowsPhoneToolset(this->DefaultPlatformToolset)) {
    std::string e;
    if (this->DefaultPlatformToolset.empty()) {
      e = cmStrCat(this->GetName(), " supports Windows Phone '8.0', but not '",
                   this->SystemVersion, "'.  Check CMAKE_SYSTEM_VERSION.");
    } else {
      e = cmStrCat(
        "A Windows Phone component with CMake requires both the Windows "
        "Desktop SDK as well as the Windows Phone '",
        this->SystemVersion,
        "' SDK. Please make sure that you have both installed");
    }
    mf->IssueMessage(MessageType::FATAL_ERROR, e);
    return false;
  }
  return true;
}

bool cmGlobalVisualStudio11Generator::InitializeWindowsStore(cmMakefile* mf)
{
  if (!this->SelectWindowsStoreToolset(this->DefaultPlatformToolset)) {
    std::string e;
    if (this->DefaultPlatformToolset.empty()) {
      e = cmStrCat(this->GetName(), " supports Windows Store '8.0', but not '",
                   this->SystemVersion, "'.  Check CMAKE_SYSTEM_VERSION.");
    } else {
      e = cmStrCat(
        "A Windows Store component with CMake requires both the Windows "
        "Desktop SDK as well as the Windows Store '",
        this->SystemVersion,
        "' SDK. Please make sure that you have both installed");
    }
    mf->IssueMessage(MessageType::FATAL_ERROR, e);
    return false;
  }
  return true;
}

bool cmGlobalVisualStudio11Generator::SelectWindowsPhoneToolset(
  std::string& toolset) const
{
  if (this->SystemVersion == "8.0"_s) {
    if (this->IsWindowsPhoneToolsetInstalled() &&
        this->IsWindowsDesktopToolsetInstalled()) {
      toolset = "v110_wp80";
      return true;
    }
    return false;
  }
  return this->cmGlobalVisualStudio10Generator::SelectWindowsPhoneToolset(
    toolset);
}

bool cmGlobalVisualStudio11Generator::SelectWindowsStoreToolset(
  std::string& toolset) const
{
  if (this->SystemVersion == "8.0"_s) {
    if (this->IsWindowsStoreToolsetInstalled() &&
        this->IsWindowsDesktopToolsetInstalled()) {
      toolset = "v110";
      return true;
    }
    return false;
  }
  return this->cmGlobalVisualStudio10Generator::SelectWindowsStoreToolset(
    toolset);
}

bool cmGlobalVisualStudio11Generator::UseFolderProperty() const
{
  // Intentionally skip up to the top-level class implementation.
  // Folders are not supported by the Express editions in VS10 and earlier,
  // but they are in VS11 Express and above.
  // NOLINTNEXTLINE(bugprone-parent-virtual-call)
  return cmGlobalGenerator::UseFolderProperty();
}

std::set<std::string>
cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs()
{
  char const sdksKey[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
                         "Windows CE Tools\\SDKs";

  std::vector<std::string> subkeys;
  cmSystemTools::GetRegistrySubKeys(sdksKey, subkeys,
                                    cmSystemTools::KeyWOW64_32);

  std::set<std::string> ret;
  for (std::string const& i : subkeys) {
    std::string key = sdksKey;
    key += '\\';
    key += i;
    key += ';';

    std::string path;
    if (cmSystemTools::ReadRegistryValue(key, path,
                                         cmSystemTools::KeyWOW64_32) &&
        !path.empty()) {
      ret.insert(i);
    }
  }

  return ret;
}

bool cmGlobalVisualStudio11Generator::TargetSystemSupportsDeployment() const
{
  return this->SystemIsWindowsPhone || this->SystemIsWindowsStore ||
    cmGlobalVisualStudio10Generator::TargetSystemSupportsDeployment();
}

bool cmGlobalVisualStudio11Generator::IsWindowsDesktopToolsetInstalled() const
{
  char const desktop80Key[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
                              "VisualStudio\\11.0\\VC\\Libraries\\Extended";
  char const VS2012DesktopExpressKey[] =
    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
    "WDExpress\\11.0;InstallDir";

  std::vector<std::string> subkeys;
  std::string path;
  return cmSystemTools::ReadRegistryValue(VS2012DesktopExpressKey, path,
                                          cmSystemTools::KeyWOW64_32) ||
    cmSystemTools::GetRegistrySubKeys(desktop80Key, subkeys,
                                      cmSystemTools::KeyWOW64_32);
}

bool cmGlobalVisualStudio11Generator::IsWindowsPhoneToolsetInstalled() const
{
  char const wp80Key[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
                         "Microsoft SDKs\\WindowsPhone\\v8.0\\"
                         "Install Path;Install Path";

  std::string path;
  cmSystemTools::ReadRegistryValue(wp80Key, path, cmSystemTools::KeyWOW64_32);
  return !path.empty();
}

bool cmGlobalVisualStudio11Generator::IsWindowsStoreToolsetInstalled() const
{
  char const win80Key[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
                          "VisualStudio\\11.0\\VC\\Libraries\\Core\\Arm";

  std::vector<std::string> subkeys;
  return cmSystemTools::GetRegistrySubKeys(win80Key, subkeys,
                                           cmSystemTools::KeyWOW64_32);
}
