// ExtractingFilePath.cpp

#include "StdAfx.h"

#include "../../../../C/Types.h"

#include "Common/Wildcard.h"

#include "ExtractingFilePath.h"

static UString ReplaceIncorrectChars(const UString &s)
{
  #ifdef _WIN32
  UString res;
  for (int i = 0; i < s.Length(); i++)
  {
    wchar_t c = s[i];
    if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>'  || c == '|' || c == ':' || c == '"')
      c = '_';
    res += c;
  }
  res.TrimRight();
  while (!res.IsEmpty() && res[res.Length() - 1] == '.')
    res.Delete(res.Length() - 1);
  return res;
  #else
  return s;
  #endif
}

#ifdef _WIN32
static const wchar_t *g_ReservedNames[] =
{
  L"CON", L"PRN", L"AUX", L"NUL"
};

static bool CheckTail(const UString &name, int len)
{
  int dotPos = name.Find(L'.');
  if (dotPos < 0)
    dotPos = name.Length();
  UString s = name.Left(dotPos);
  s.TrimRight();
  return (s.Length() != len);
}

static bool CheckNameNum(const UString &name, const wchar_t *reservedName)
{
  int len = MyStringLen(reservedName);
  if (name.Length() <= len)
    return true;
  if (name.Left(len).CompareNoCase(reservedName) != 0)
    return true;
  wchar_t c = name[len];
  if (c < L'0' || c > L'9')
    return true;
  return CheckTail(name, len + 1);
}

static bool IsSupportedName(const UString &name)
{
  for (int i = 0; i < sizeof(g_ReservedNames) / sizeof(g_ReservedNames[0]); i++)
  {
    const wchar_t *reservedName = g_ReservedNames[i];
    int len = MyStringLen(reservedName);
    if (name.Length() < len)
      continue;
    if (name.Left(len).CompareNoCase(reservedName) != 0)
      continue;
    if (!CheckTail(name, len))
      return false;
  }
  if (!CheckNameNum(name, L"COM"))
    return false;
  return CheckNameNum(name, L"LPT");
}
#endif

static UString GetCorrectFileName(const UString &path)
{
  if (path == L".." || path == L".")
    return UString();
  return ReplaceIncorrectChars(path);
}

void MakeCorrectPath(UStringVector &pathParts)
{
  for (int i = 0; i < pathParts.Size();)
  {
    UString &s = pathParts[i];
    s = GetCorrectFileName(s);
    if (s.IsEmpty())
      pathParts.Delete(i);
    else
    {
      #ifdef _WIN32
      if (!IsSupportedName(s))
        s = (UString)L"_" + s;
      #endif
      i++;
    }
  }
}

UString MakePathNameFromParts(const UStringVector &parts)
{
  UString result;
  for (int i = 0; i < parts.Size(); i++)
  {
    if (i != 0)
      result += WCHAR_PATH_SEPARATOR;
    result += parts[i];
  }
  return result;
}

UString GetCorrectFsPath(const UString &path)
{
  UString res = GetCorrectFileName(path);
  #ifdef _WIN32
  if (!IsSupportedName(res))
    res = (UString)L"_" + res;
  #endif
  return res;
}
  
UString GetCorrectFullFsPath(const UString &path)
{
  UStringVector parts;
  SplitPathToParts(path, parts);
  for (int i = 0; i < parts.Size(); i++)
  {
    UString &s = parts[i];
    #ifdef _WIN32
    while (!s.IsEmpty() && s[s.Length() - 1] == '.')
      s.Delete(s.Length() - 1);
    if (!IsSupportedName(s))
      s = (UString)L"_" + s;
    #endif
  }
  return MakePathNameFromParts(parts);
}
