/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */
#ifdef __osf__
#  define _OSF_SOURCE
#  define _POSIX_C_SOURCE 199506L
#  define _XOPEN_SOURCE_EXTENDED
#endif

#include "kwsysPrivate.h"
#include KWSYS_HEADER(Encoding.hxx)
#include KWSYS_HEADER(Encoding.h)

// Work-around CMake dependency scanning limitation.  This must
// duplicate the above list of headers.
#if 0
#  include "Encoding.h.in"
#  include "Encoding.hxx.in"
#endif

#include <stdlib.h>
#include <string.h>
#include <vector>

#ifdef _MSC_VER
#  pragma warning(disable : 4786)
#endif

// Windows API.
#if defined(_WIN32)
#  include <windows.h>

#  include <ctype.h>
#  include <shellapi.h>
#endif

namespace KWSYS_NAMESPACE {

Encoding::CommandLineArguments Encoding::CommandLineArguments::Main(
  int argc, char const* const* argv)
{
#ifdef _WIN32
  (void)argc;
  (void)argv;

  int ac;
  LPWSTR* w_av = CommandLineToArgvW(GetCommandLineW(), &ac);

  std::vector<std::string> av1(ac);
  std::vector<char const*> av2(ac);
  for (int i = 0; i < ac; i++) {
    av1[i] = ToNarrow(w_av[i]);
    av2[i] = av1[i].c_str();
  }
  LocalFree(w_av);
  return CommandLineArguments(ac, &av2[0]);
#else
  return CommandLineArguments(argc, argv);
#endif
}

Encoding::CommandLineArguments::CommandLineArguments(int ac,
                                                     char const* const* av)
{
  this->argv_.resize(ac + 1);
  for (int i = 0; i < ac; i++) {
    this->argv_[i] = strdup(av[i]);
  }
  this->argv_[ac] = KWSYS_NULLPTR;
}

Encoding::CommandLineArguments::CommandLineArguments(int ac,
                                                     wchar_t const* const* av)
{
  this->argv_.resize(ac + 1);
  for (int i = 0; i < ac; i++) {
    this->argv_[i] = kwsysEncoding_DupToNarrow(av[i]);
  }
  this->argv_[ac] = KWSYS_NULLPTR;
}

Encoding::CommandLineArguments::~CommandLineArguments()
{
  for (size_t i = 0; i < this->argv_.size(); i++) {
    free(argv_[i]);
  }
}

Encoding::CommandLineArguments::CommandLineArguments(
  const CommandLineArguments& other)
{
  this->argv_.resize(other.argv_.size());
  for (size_t i = 0; i < this->argv_.size(); i++) {
    this->argv_[i] = other.argv_[i] ? strdup(other.argv_[i]) : KWSYS_NULLPTR;
  }
}

Encoding::CommandLineArguments& Encoding::CommandLineArguments::operator=(
  const CommandLineArguments& other)
{
  if (this != &other) {
    size_t i;
    for (i = 0; i < this->argv_.size(); i++) {
      free(this->argv_[i]);
    }

    this->argv_.resize(other.argv_.size());
    for (i = 0; i < this->argv_.size(); i++) {
      this->argv_[i] = other.argv_[i] ? strdup(other.argv_[i]) : KWSYS_NULLPTR;
    }
  }

  return *this;
}

int Encoding::CommandLineArguments::argc() const
{
  return static_cast<int>(this->argv_.size() - 1);
}

char const* const* Encoding::CommandLineArguments::argv() const
{
  return &this->argv_[0];
}

#if KWSYS_STL_HAS_WSTRING

std::wstring Encoding::ToWide(const std::string& str)
{
  std::wstring wstr;
#  if defined(_WIN32)
  const int wlength = MultiByteToWideChar(
    KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.data(), int(str.size()), NULL, 0);
  if (wlength > 0) {
    wchar_t* wdata = new wchar_t[wlength];
    int r = MultiByteToWideChar(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.data(),
                                int(str.size()), wdata, wlength);
    if (r > 0) {
      wstr = std::wstring(wdata, wlength);
    }
    delete[] wdata;
  }
#  else
  size_t pos = 0;
  size_t nullPos = 0;
  do {
    if (pos < str.size() && str.at(pos) != '\0') {
      wstr += ToWide(str.c_str() + pos);
    }
    nullPos = str.find('\0', pos);
    if (nullPos != std::string::npos) {
      pos = nullPos + 1;
      wstr += wchar_t('\0');
    }
  } while (nullPos != std::string::npos);
#  endif
  return wstr;
}

std::string Encoding::ToNarrow(const std::wstring& str)
{
  std::string nstr;
#  if defined(_WIN32)
  int length =
    WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.c_str(),
                        int(str.size()), NULL, 0, NULL, NULL);
  if (length > 0) {
    char* data = new char[length];
    int r =
      WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.c_str(),
                          int(str.size()), data, length, NULL, NULL);
    if (r > 0) {
      nstr = std::string(data, length);
    }
    delete[] data;
  }
#  else
  size_t pos = 0;
  size_t nullPos = 0;
  do {
    if (pos < str.size() && str.at(pos) != '\0') {
      nstr += ToNarrow(str.c_str() + pos);
    }
    nullPos = str.find(wchar_t('\0'), pos);
    if (nullPos != std::string::npos) {
      pos = nullPos + 1;
      nstr += '\0';
    }
  } while (nullPos != std::string::npos);
#  endif
  return nstr;
}

std::wstring Encoding::ToWide(const char* cstr)
{
  std::wstring wstr;
  size_t length = kwsysEncoding_mbstowcs(KWSYS_NULLPTR, cstr, 0) + 1;
  if (length > 0) {
    std::vector<wchar_t> wchars(length);
    if (kwsysEncoding_mbstowcs(&wchars[0], cstr, length) > 0) {
      wstr = &wchars[0];
    }
  }
  return wstr;
}

std::string Encoding::ToNarrow(const wchar_t* wcstr)
{
  std::string str;
  size_t length = kwsysEncoding_wcstombs(KWSYS_NULLPTR, wcstr, 0) + 1;
  if (length > 0) {
    std::vector<char> chars(length);
    if (kwsysEncoding_wcstombs(&chars[0], wcstr, length) > 0) {
      str = &chars[0];
    }
  }
  return str;
}

#  if defined(_WIN32)
// Convert local paths to UNC style paths
std::wstring Encoding::ToWindowsExtendedPath(std::string const& source)
{
  std::wstring wsource = Encoding::ToWide(source);

  // Resolve any relative paths
  DWORD wfull_len;

  /* The +3 is a workaround for a bug in some versions of GetFullPathNameW that
   * won't return a large enough buffer size if the input is too small */
  wfull_len = GetFullPathNameW(wsource.c_str(), 0, NULL, NULL) + 3;
  std::vector<wchar_t> wfull(wfull_len);
  GetFullPathNameW(wsource.c_str(), wfull_len, &wfull[0], NULL);

  /* This should get the correct size without any extra padding from the
   * previous size workaround. */
  wfull_len = static_cast<DWORD>(wcslen(&wfull[0]));

  if (wfull_len >= 2 && isalpha(wfull[0]) &&
      wfull[1] == L':') { /* C:\Foo\bar\FooBar.txt */
    return L"\\\\?\\" + std::wstring(&wfull[0]);
  } else if (wfull_len >= 2 && wfull[0] == L'\\' &&
             wfull[1] == L'\\') { /* Starts with \\ */
    if (wfull_len >= 4 && wfull[2] == L'?' &&
        wfull[3] == L'\\') { /* Starts with \\?\ */
      if (wfull_len >= 8 && wfull[4] == L'U' && wfull[5] == L'N' &&
          wfull[6] == L'C' &&
          wfull[7] == L'\\') { /* \\?\UNC\Foo\bar\FooBar.txt */
        return std::wstring(&wfull[0]);
      } else if (wfull_len >= 6 && isalpha(wfull[4]) &&
                 wfull[5] == L':') { /* \\?\C:\Foo\bar\FooBar.txt */
        return std::wstring(&wfull[0]);
      } else if (wfull_len >= 5) { /* \\?\Foo\bar\FooBar.txt */
        return L"\\\\?\\UNC\\" + std::wstring(&wfull[4]);
      }
    } else if (wfull_len >= 4 && wfull[2] == L'.' &&
               wfull[3] == L'\\') { /* Starts with \\.\ a device name */
      if (wfull_len >= 6 && isalpha(wfull[4]) &&
          wfull[5] == L':') { /* \\.\C:\Foo\bar\FooBar.txt */
        return L"\\\\?\\" + std::wstring(&wfull[4]);
      } else if (wfull_len >=
                 5) { /* \\.\Foo\bar\ Device name is left unchanged */
        return std::wstring(&wfull[0]);
      }
    } else if (wfull_len >= 3) { /* \\Foo\bar\FooBar.txt */
      return L"\\\\?\\UNC\\" + std::wstring(&wfull[2]);
    }
  }

  // If this case has been reached, then the path is invalid.  Leave it
  // unchanged
  return Encoding::ToWide(source);
}
#  endif

#endif // KWSYS_STL_HAS_WSTRING

} // namespace KWSYS_NAMESPACE
