//          Copyright Carl Philipp Reh 2009 - 2021.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#include <fcppt/string.hpp>
#include <fcppt/system.hpp>
#include <fcppt/config/platform.hpp>
#include <fcppt/optional/object_impl.hpp>
#ifdef FCPPT_CONFIG_POSIX_PLATFORM
#include <fcppt/system_conversion_failed.hpp>
#include <fcppt/strong_typedef_impl.hpp> // IWYU pragma: keep
#include <fcppt/to_std_string.hpp>
#include <fcppt/optional/make_if.hpp>
#include <fcppt/optional/to_exception.hpp>
#include <fcppt/preprocessor/disable_gcc_warning.hpp>
#include <fcppt/preprocessor/pop_warning.hpp>
#include <fcppt/preprocessor/push_warning.hpp>
#include <fcppt/config/external_begin.hpp>
#include <sys/types.h> // IWYU pragma: keep
#include <sys/wait.h> // IWYU pragma: keep
#include <cstdlib>
#include <fcppt/config/external_end.hpp>
#elifdef FCPPT_CONFIG_WINDOWS_PLATFORM
#include <fcppt/const.hpp>
#include <fcppt/public_config.hpp>
#include <fcppt/optional/make_if.hpp>
#include <fcppt/config/external_begin.hpp>
#include <cstdlib>
#include <fcppt/config/external_end.hpp>

#endif

fcppt::optional::object<int> fcppt::system(fcppt::string const &_command)
{
#ifdef FCPPT_CONFIG_POSIX_PLATFORM
  int const result{// NOLINTNEXTLINE(cert-env33-c,concurrency-mt-unsafe,bugprone-command-processor)
                   ::system(
                       fcppt::optional::to_exception(
                           fcppt::to_std_string(_command),
                           [&_command]
                           {
                             return fcppt::system_conversion_failed{
                                 fcppt::system_conversion_failed::command_type{_command}};
                           })
                           .c_str())};

  FCPPT_PP_PUSH_WARNING
  FCPPT_PP_DISABLE_GCC_WARNING(-Wcast-qual)
  return fcppt::optional::make_if(
      // NOLINTNEXTLINE(hicpp-signed-bitwise)
      WIFEXITED(result), // NOLINT(misc-include-cleaner)
      [result] {
        return
            // NOLINTNEXTLINE(hicpp-signed-bitwise)
            WEXITSTATUS(result); // NOLINT(misc-include-cleaner)
      });
FCPPT_PP_POP_WARNING
#elifdef FCPPT_CONFIG_WINDOWS_PLATFORM
  int const result
  {
#ifdef FCPPT_NARROW_STRING
    ::system(
#else
    _wsystem(
#endif
        _command.c_str())
  };

  return fcppt::optional::make_if(result != -1, fcppt::const_(result));
#else
#error "Implement me!"
#endif
}
