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

#include <algorithm>
#include <cassert>
#include <cctype>
#include <cstddef>
#include <initializer_list>
#include <map>
#include <string>
#include <utility>

#include <cm/optional>
#include <cm/string_view>
#include <cmext/string_view>

#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
#include "cmsys/SystemInformation.hxx"

#include "cmArgumentParser.h"
#include "cmExecutionStatus.h"
#include "cmList.h"
#include "cmMakefile.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"
#include "cmWindowsRegistry.h"

#ifdef _WIN32
#  include "cmAlgorithms.h"
#  include "cmGlobalGenerator.h"
#  include "cmGlobalVisualStudio10Generator.h"
#  include "cmGlobalVisualStudioVersionedGenerator.h"
#  include "cmVSSetupHelper.h"
#endif

namespace {
std::string const DELIM[2] = { {}, ";" };

// BEGIN Private functions
std::string ValueToString(std::size_t const value)
{
  return std::to_string(value);
}

std::string ValueToString(const char* const value)
{
  return value ? value : std::string{};
}

std::string ValueToString(std::string const& value)
{
  return value;
}

cm::optional<std::string> GetValue(cmsys::SystemInformation& info,
                                   std::string const& key)
{
  if (key == "NUMBER_OF_LOGICAL_CORES"_s) {
    return ValueToString(info.GetNumberOfLogicalCPU());
  }
  if (key == "NUMBER_OF_PHYSICAL_CORES"_s) {
    return ValueToString(info.GetNumberOfPhysicalCPU());
  }
  if (key == "HOSTNAME"_s) {
    return ValueToString(info.GetHostname());
  }
  if (key == "FQDN"_s) {
    return ValueToString(info.GetFullyQualifiedDomainName());
  }
  if (key == "TOTAL_VIRTUAL_MEMORY"_s) {
    return ValueToString(info.GetTotalVirtualMemory());
  }
  if (key == "AVAILABLE_VIRTUAL_MEMORY"_s) {
    return ValueToString(info.GetAvailableVirtualMemory());
  }
  if (key == "TOTAL_PHYSICAL_MEMORY"_s) {
    return ValueToString(info.GetTotalPhysicalMemory());
  }
  if (key == "AVAILABLE_PHYSICAL_MEMORY"_s) {
    return ValueToString(info.GetAvailablePhysicalMemory());
  }
  if (key == "IS_64BIT"_s) {
    return ValueToString(info.Is64Bits());
  }
  if (key == "HAS_FPU"_s) {
    return ValueToString(
      info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_FPU));
  }
  if (key == "HAS_MMX"_s) {
    return ValueToString(
      info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_MMX));
  }
  if (key == "HAS_MMX_PLUS"_s) {
    return ValueToString(info.DoesCPUSupportFeature(
      cmsys::SystemInformation::CPU_FEATURE_MMX_PLUS));
  }
  if (key == "HAS_SSE"_s) {
    return ValueToString(
      info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE));
  }
  if (key == "HAS_SSE2"_s) {
    return ValueToString(
      info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE2));
  }
  if (key == "HAS_SSE_FP"_s) {
    return ValueToString(info.DoesCPUSupportFeature(
      cmsys::SystemInformation::CPU_FEATURE_SSE_FP));
  }
  if (key == "HAS_SSE_MMX"_s) {
    return ValueToString(info.DoesCPUSupportFeature(
      cmsys::SystemInformation::CPU_FEATURE_SSE_MMX));
  }
  if (key == "HAS_AMD_3DNOW"_s) {
    return ValueToString(info.DoesCPUSupportFeature(
      cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW));
  }
  if (key == "HAS_AMD_3DNOW_PLUS"_s) {
    return ValueToString(info.DoesCPUSupportFeature(
      cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW_PLUS));
  }
  if (key == "HAS_IA64"_s) {
    return ValueToString(
      info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_IA64));
  }
  if (key == "HAS_SERIAL_NUMBER"_s) {
    return ValueToString(info.DoesCPUSupportFeature(
      cmsys::SystemInformation::CPU_FEATURE_SERIALNUMBER));
  }
  if (key == "PROCESSOR_NAME"_s) {
    return ValueToString(info.GetExtendedProcessorName());
  }
  if (key == "PROCESSOR_DESCRIPTION"_s) {
    return info.GetCPUDescription();
  }
  if (key == "PROCESSOR_SERIAL_NUMBER"_s) {
    return ValueToString(info.GetProcessorSerialNumber());
  }
  if (key == "OS_NAME"_s) {
    return ValueToString(info.GetOSName());
  }
  if (key == "OS_RELEASE"_s) {
    return ValueToString(info.GetOSRelease());
  }
  if (key == "OS_VERSION"_s) {
    return ValueToString(info.GetOSVersion());
  }
  if (key == "OS_PLATFORM"_s) {
    return ValueToString(info.GetOSPlatform());
  }
  return {};
}

cm::optional<std::pair<std::string, std::string>> ParseOSReleaseLine(
  std::string const& line)
{
  std::string key;
  std::string value;

  char prev = 0;
  enum ParserState
  {
    PARSE_KEY_1ST,
    PARSE_KEY,
    FOUND_EQ,
    PARSE_SINGLE_QUOTE_VALUE,
    PARSE_DBL_QUOTE_VALUE,
    PARSE_VALUE,
    IGNORE_REST
  } state = PARSE_KEY_1ST;

  for (auto ch : line) {
    switch (state) {
      case PARSE_KEY_1ST:
        if (std::isalpha(ch) || ch == '_') {
          key += ch;
          state = PARSE_KEY;
        } else if (!cmIsSpace(ch)) {
          state = IGNORE_REST;
        }
        break;

      case PARSE_KEY:
        if (ch == '=') {
          state = FOUND_EQ;
        } else if (std::isalnum(ch) || ch == '_') {
          key += ch;
        } else {
          state = IGNORE_REST;
        }
        break;

      case FOUND_EQ:
        switch (ch) {
          case '\'':
            state = PARSE_SINGLE_QUOTE_VALUE;
            break;
          case '"':
            state = PARSE_DBL_QUOTE_VALUE;
            break;
          case '#':
          case '\\':
            state = IGNORE_REST;
            break;
          default:
            value += ch;
            state = PARSE_VALUE;
        }
        break;

      case PARSE_SINGLE_QUOTE_VALUE:
        if (ch == '\'') {
          if (prev != '\\') {
            state = IGNORE_REST;
          } else {
            assert(!value.empty());
            value[value.size() - 1] = ch;
          }
        } else {
          value += ch;
        }
        break;

      case PARSE_DBL_QUOTE_VALUE:
        if (ch == '"') {
          if (prev != '\\') {
            state = IGNORE_REST;
          } else {
            assert(!value.empty());
            value[value.size() - 1] = ch;
          }
        } else {
          value += ch;
        }
        break;

      case PARSE_VALUE:
        if (ch == '#' || cmIsSpace(ch)) {
          state = IGNORE_REST;
        } else {
          value += ch;
        }
        break;

      default:
        // Unexpected os-release parser state!
        state = IGNORE_REST;
        break;
    }

    if (state == IGNORE_REST) {
      break;
    }
    prev = ch;
  }
  if (!(key.empty() || value.empty())) {
    return std::make_pair(key, value);
  }
  return {};
}

std::map<std::string, std::string> GetOSReleaseVariables(
  cmExecutionStatus& status)
{
  auto& makefile = status.GetMakefile();
  const auto& sysroot = makefile.GetSafeDefinition("CMAKE_SYSROOT");

  std::map<std::string, std::string> data;
  // Based on
  // https://www.freedesktop.org/software/systemd/man/latest/os-release.html
  for (auto name : { "/etc/os-release"_s, "/usr/lib/os-release"_s }) {
    const auto& filename = cmStrCat(sysroot, name);
    if (cmSystemTools::FileExists(filename)) {
      cmsys::ifstream fin(filename.c_str());
      for (std::string line; !std::getline(fin, line).fail();) {
        auto kv = ParseOSReleaseLine(line);
        if (kv.has_value()) {
          data.emplace(kv.value());
        }
      }
      break;
    }
  }
  // Got smth?
  if (!data.empty()) {
    return data;
  }

  // Ugh, it could be some pre-os-release distro.
  // Lets try some fallback getters.
  // See also:
  //  - http://linuxmafia.com/faq/Admin/release-files.html

  // 1. CMake provided
  cmsys::Glob gl;
  std::vector<std::string> scripts;
  auto const findExpr = cmStrCat(cmSystemTools::GetCMakeRoot(),
                                 "/Modules/Internal/OSRelease/*.cmake");
  if (gl.FindFiles(findExpr)) {
    scripts = gl.GetFiles();
  }

  // 2. User provided (append to the CMake prvided)
  cmList::append(
    scripts, makefile.GetDefinition("CMAKE_GET_OS_RELEASE_FALLBACK_SCRIPTS"));

  // Filter out files that are not in format `NNN-name.cmake`
  auto checkName = [](std::string const& filepath) -> bool {
    auto const& filename = cmSystemTools::GetFilenameName(filepath);
    // NOTE Minimum filename length expected:
    //   NNN-<at-least-one-char-name>.cmake  --> 11
    return (filename.size() < 11) || !std::isdigit(filename[0]) ||
      !std::isdigit(filename[1]) || !std::isdigit(filename[2]) ||
      filename[3] != '-';
  };
  scripts.erase(std::remove_if(scripts.begin(), scripts.end(), checkName),
                scripts.end());

  // Make sure scripts are running in desired order
  std::sort(scripts.begin(), scripts.end(),
            [](std::string const& lhs, std::string const& rhs) -> bool {
              long lhs_order;
              cmStrToLong(cmSystemTools::GetFilenameName(lhs).substr(0u, 3u),
                          &lhs_order);
              long rhs_order;
              cmStrToLong(cmSystemTools::GetFilenameName(rhs).substr(0u, 3u),
                          &rhs_order);
              return lhs_order < rhs_order;
            });

  // Name of the variable to put the results
  std::string const result_variable{ "CMAKE_GET_OS_RELEASE_FALLBACK_RESULT" };

  for (auto const& script : scripts) {
    // Unset the result variable
    makefile.RemoveDefinition(result_variable);

    // include FATAL_ERROR and ERROR in the return status
    if (!makefile.ReadListFile(script) ||
        cmSystemTools::GetErrorOccurredFlag()) {
      // Ok, no worries... go try the next script.
      continue;
    }

    cmList variables{ makefile.GetDefinition(result_variable) };
    if (variables.empty()) {
      // Heh, this script didn't found anything... go try the next one.
      continue;
    }

    for (auto const& variable : variables) {
      auto value = makefile.GetSafeDefinition(variable);
      makefile.RemoveDefinition(variable);

      if (!cmHasPrefix(variable, cmStrCat(result_variable, '_'))) {
        // Ignore unknown variable set by the script
        continue;
      }

      auto key = variable.substr(result_variable.size() + 1,
                                 variable.size() - result_variable.size() - 1);
      data.emplace(std::move(key), std::move(value));
    }

    // Try 'till some script can get anything
    if (!data.empty()) {
      data.emplace("USED_FALLBACK_SCRIPT", script);
      break;
    }
  }

  makefile.RemoveDefinition(result_variable);

  return data;
}

cm::optional<std::string> GetDistribValue(cmExecutionStatus& status,
                                          std::string const& key,
                                          std::string const& variable)
{
  const auto prefix = "DISTRIB_"_s;
  if (!cmHasPrefix(key, prefix)) {
    return {};
  }

  static const std::map<std::string, std::string> s_os_release =
    GetOSReleaseVariables(status);

  auto& makefile = status.GetMakefile();

  const std::string subkey =
    key.substr(prefix.size(), key.size() - prefix.size());
  if (subkey == "INFO"_s) {
    std::string vars;
    for (const auto& kv : s_os_release) {
      auto cmake_var_name = cmStrCat(variable, '_', kv.first);
      vars += DELIM[!vars.empty()] + cmake_var_name;
      makefile.AddDefinition(cmake_var_name, kv.second);
    }
    return cm::optional<std::string>(std::move(vars));
  }

  // Query individual variable
  const auto it = s_os_release.find(subkey);
  if (it != s_os_release.cend()) {
    return it->second;
  }

  // NOTE Empty string means requested variable not set
  return std::string{};
}

#ifdef _WIN32
std::string FindMSYSTEM_PREFIX(std::vector<std::string> prefixes)
{
  for (std::string const& prefix : prefixes) {
    std::string out;
    std::string err;
    int ret;
    // In a modern MSYSTEM environment we expect cygpath to be in PATH.
    std::vector<std::string> cygpath_cmd{ "cygpath", "-w", prefix };
    if (cmSystemTools::RunSingleCommand(cygpath_cmd, &out, &err, &ret, nullptr,
                                        cmSystemTools::OUTPUT_NONE)) {
      if (ret == 0) {
        out = cmTrimWhitespace(out);
        cmSystemTools::ConvertToUnixSlashes(out);
        if (cmSystemTools::FileIsDirectory(out)) {
          return out;
        }
      }
    } else {
      // In a legacy MSYSTEM environment (MinGW/MSYS 1.0) there is no
      // cygpath but we expect 'sh' to be in PATH.
      std::vector<std::string> sh_cmd{
        "sh", "-c", cmStrCat("cd \"", prefix, "\" && cmd //c cd")
      };
      if (cmSystemTools::RunSingleCommand(sh_cmd, &out, &err, &ret, nullptr,
                                          cmSystemTools::OUTPUT_NONE)) {
        if (ret == 0) {
          out = cmTrimWhitespace(out);
          cmSystemTools::ConvertToUnixSlashes(out);
          if (cmSystemTools::FileIsDirectory(out)) {
            return out;
          }
        }
      }
    }
  }
  return {};
}

std::string FallbackMSYSTEM_PREFIX(cm::string_view msystem)
{
  // These layouts are used by distributions such as
  // * MSYS2: https://www.msys2.org/docs/environments/
  // * MinGW/MSYS 1.0: http://mingw.osdn.io/
  if (msystem == "MSYS"_s) {
    static std::string const msystem_msys = FindMSYSTEM_PREFIX({ "/usr" });
    return msystem_msys;
  }
  if (msystem == "MINGW32"_s) {
    static std::string const msystem_mingw32 =
      FindMSYSTEM_PREFIX({ "/mingw32", "/mingw" });
    return msystem_mingw32;
  }
  if (msystem == "MINGW64"_s) {
    static std::string const msystem_mingw64 =
      FindMSYSTEM_PREFIX({ "/mingw64" });
    return msystem_mingw64;
  }
  if (msystem == "UCRT64"_s) {
    static std::string const msystem_ucrt64 =
      FindMSYSTEM_PREFIX({ "/ucrt64" });
    return msystem_ucrt64;
  }
  if (msystem == "CLANG32"_s) {
    static std::string const msystem_clang32 =
      FindMSYSTEM_PREFIX({ "/clang32" });
    return msystem_clang32;
  }
  if (msystem == "CLANG64"_s) {
    static std::string const msystem_clang64 =
      FindMSYSTEM_PREFIX({ "/clang64" });
    return msystem_clang64;
  }
  if (msystem == "CLANGARM64"_s) {
    static std::string const msystem_clangarm64 =
      FindMSYSTEM_PREFIX({ "/clangarm64" });
    return msystem_clangarm64;
  }
  return {};
}

cm::optional<std::string> GetWindowsValue(cmExecutionStatus& status,
                                          std::string const& key)
{
  auto* const gg = status.GetMakefile().GetGlobalGenerator();
  for (auto vs : { 15, 16, 17 }) {
    if (key == cmStrCat("VS_"_s, vs, "_DIR"_s)) {
      std::string value;
      // If generating for the VS nn IDE, use the same instance.

      if (cmHasPrefix(gg->GetName(), cmStrCat("Visual Studio "_s, vs, ' '))) {
        cmGlobalVisualStudioVersionedGenerator* vsNNgen =
          static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg);
        if (vsNNgen->GetVSInstance(value)) {
          return value;
        }
      }

      // Otherwise, find a VS nn instance ourselves.
      cmVSSetupAPIHelper vsSetupAPIHelper(vs);
      if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
        cmSystemTools::ConvertToUnixSlashes(value);
      }
      return value;
    }
  }

  if (key == "VS_MSBUILD_COMMAND"_s && gg->IsVisualStudioAtLeast10()) {
    cmGlobalVisualStudio10Generator* vs10gen =
      static_cast<cmGlobalVisualStudio10Generator*>(gg);
    return vs10gen->FindMSBuildCommandEarly(&status.GetMakefile());
  }

  if (key == "MSYSTEM_PREFIX") {
    // MSYSTEM_PREFIX is meaningful only under a MSYSTEM environment.
    cm::optional<std::string> ms = cmSystemTools::GetEnvVar("MSYSTEM");
    if (!ms || ms->empty()) {
      return std::string();
    }
    // Prefer the MSYSTEM_PREFIX environment variable.
    if (cm::optional<std::string> msp =
          cmSystemTools::GetEnvVar("MSYSTEM_PREFIX")) {
      cmSystemTools::ConvertToUnixSlashes(*msp);
      if (cmSystemTools::FileIsDirectory(*msp)) {
        return msp;
      }
    }
    // Fall back to known distribution layouts.
    return FallbackMSYSTEM_PREFIX(*ms);
  }
  return {};
}
#endif

cm::optional<std::string> GetValueChained()
{
  return {};
}

template <typename GetterFn, typename... Next>
cm::optional<std::string> GetValueChained(GetterFn current, Next... chain)
{
  auto value = current();
  if (value.has_value()) {
    return value;
  }
  return GetValueChained(chain...);
}

template <typename Range>
bool QueryWindowsRegistry(Range args, cmExecutionStatus& status,
                          std::string const& variable)
{
  using View = cmWindowsRegistry::View;
  if (args.empty()) {
    status.SetError("missing <key> specification.");
    return false;
  }
  std::string const& key = *args.begin();

  struct Arguments : public ArgumentParser::ParseResult
  {
    std::string ValueName;
    bool ValueNames = false;
    bool SubKeys = false;
    std::string View;
    std::string Separator;
    std::string ErrorVariable;
  };
  cmArgumentParser<Arguments> parser;
  parser.Bind("VALUE"_s, &Arguments::ValueName)
    .Bind("VALUE_NAMES"_s, &Arguments::ValueNames)
    .Bind("SUBKEYS"_s, &Arguments::SubKeys)
    .Bind("VIEW"_s, &Arguments::View)
    .Bind("SEPARATOR"_s, &Arguments::Separator)
    .Bind("ERROR_VARIABLE"_s, &Arguments::ErrorVariable);
  std::vector<std::string> invalidArgs;

  Arguments const arguments = parser.Parse(args.advance(1), &invalidArgs);
  if (!invalidArgs.empty()) {
    status.SetError(cmStrCat("given invalid argument(s) \"",
                             cmJoin(invalidArgs, ", "_s), "\"."));
    return false;
  }
  if (arguments.MaybeReportError(status.GetMakefile())) {
    return true;
  }
  if ((!arguments.ValueName.empty() &&
       (arguments.ValueNames || arguments.SubKeys)) ||
      (arguments.ValueName.empty() && arguments.ValueNames &&
       arguments.SubKeys)) {
    status.SetError("given mutually exclusive sub-options \"VALUE\", "
                    "\"VALUE_NAMES\" or \"SUBKEYS\".");
    return false;
  }

  if (!arguments.View.empty() && !cmWindowsRegistry::ToView(arguments.View)) {
    status.SetError(
      cmStrCat("given invalid value for \"VIEW\": ", arguments.View, '.'));
    return false;
  }

  auto& makefile = status.GetMakefile();

  makefile.AddDefinition(variable, ""_s);

  auto view = arguments.View.empty()
    ? View::Both
    : *cmWindowsRegistry::ToView(arguments.View);
  cmWindowsRegistry registry(makefile);
  if (arguments.ValueNames) {
    auto result = registry.GetValueNames(key, view);
    if (result) {
      makefile.AddDefinition(variable, cmList::to_string(*result));
    }
  } else if (arguments.SubKeys) {
    auto result = registry.GetSubKeys(key, view);
    if (result) {
      makefile.AddDefinition(variable, cmList::to_string(*result));
    }
  } else {
    auto result =
      registry.ReadValue(key, arguments.ValueName, view, arguments.Separator);
    if (result) {
      makefile.AddDefinition(variable, *result);
    }
  }

  // return error message if requested
  if (!arguments.ErrorVariable.empty()) {
    makefile.AddDefinition(arguments.ErrorVariable, registry.GetLastError());
  }

  return true;
}

// END Private functions
} // anonymous namespace

// cmCMakeHostSystemInformation
bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args,
                                         cmExecutionStatus& status)
{
  std::size_t current_index = 0;

  if (args.size() < (current_index + 2) || args[current_index] != "RESULT"_s) {
    status.SetError("missing RESULT specification.");
    return false;
  }

  auto const& variable = args[current_index + 1];
  current_index += 2;

  if (args.size() < (current_index + 2) || args[current_index] != "QUERY"_s) {
    status.SetError("missing QUERY specification");
    return false;
  }

  if (args[current_index + 1] == "WINDOWS_REGISTRY"_s) {
    return QueryWindowsRegistry(cmMakeRange(args).advance(current_index + 2),
                                status, variable);
  }

  static cmsys::SystemInformation info;
  static auto initialized = false;
  if (!initialized) {
    info.RunCPUCheck();
    info.RunOSCheck();
    info.RunMemoryCheck();
    initialized = true;
  }

  std::string result_list;
  for (auto i = current_index + 1; i < args.size(); ++i) {
    result_list += DELIM[!result_list.empty()];

    auto const& key = args[i];
    // clang-format off
    auto value =
      GetValueChained(
          [&]() { return GetValue(info, key); }
        , [&]() { return GetDistribValue(status, key, variable); }
#ifdef _WIN32
        , [&]() { return GetWindowsValue(status, key); }
#endif
        );
    // clang-format on
    if (!value) {
      status.SetError("does not recognize <key> " + key);
      return false;
    }
    result_list += value.value();
  }

  status.GetMakefile().AddDefinition(variable, result_list);

  return true;
}
