#include "stdafx.h"

#include "xtr/core/Encoder.h"

#include <unordered_map>

namespace xtr::encode {

bool IsCstName(wchar_t uc) noexcept {
  switch (uc) {
  default: return false;
  case 'X': case 'C':
  case 'S': case 'H':
  case 'D': case 'A':
  case 'T': 
    return true;
  }
}

bool IsAlphaNumber(const wchar_t uc) noexcept {
  if (IsGreek(uc)) {
    return false;
  } else if (IsIndex(uc)) {
    return true;
  } else {
    return iswalnum(uc) != 0;
  }
}

void EncodeToUnicode(CString& str) {
  CString result{};
  for (auto i = 0; i < str.GetLength(); ++i) {
    result.AppendChar(Bulean2ToUnicodeChar(str[i]));
  }
  str = result;
}

uint8_t Encode1251To866(uint8_t c) noexcept {
  if ((c >= 0x80) && (c <= 0xAF)) { // NOLINT
    return static_cast<uint8_t>(c + 0x40); // NOLINT
  } else if ((c >= 0xE0) && (c <= 0xEF)) { // NOLINT
    return static_cast<uint8_t>(c + 0x10); // NOLINT
  } else if (c == 0xF0) { // NOLINT
    return 0xA8; // NOLINT
  } else if (c == 0xF1) { // NOLINT
    return 0xB8; // NOLINT
  } else {
    return c;
  }
}

wchar_t Bulean2ToUnicodeChar(wchar_t ac) {
  // Note: Преобразуем код Bulean2 в стандартную таблицу Unicode
  static const std::unordered_map<int32_t, wchar_t> codeTable = {
    { 0x23, US_GREATER_OR_EQ },
    { 0x24, US_LOGIC_EXISTS },

    { 0x40, US_LESSER_OR_EQ },

    { 0x80, US_A },  { 0x0402, US_A },
    { 0x81, US_B },  { 0x0403, US_B },
    { 0x82, US_G },  { 0x201A, US_G },
    { 0x83, US_D },  { 0x0453, US_D },
    { 0x84, US_E },  { 0x201E, US_E },
    { 0x85, US_Z },  { 0x2026, US_Z },
    { 0x86, US_H },  { 0x2020, US_H },
    { 0x87, US_V },  { 0x2021, US_V },
    { 0x8A, US_L },  { 0x0409, US_L },
    { 0x8B, US_M },  { 0x2039, US_M },
    { 0x8C, US_N },  { 0x040A, US_N },
    { 0x8D, US_X },  { 0x040C, US_X },
    { 0x8E, US_O },  { 0x040B, US_O },
    { 0x8F, US_P },  { 0x040F, US_P },
    { 0x90, US_R },  { 0x0452, US_R },
    { 0x91, US_S },  { 0x2018, US_S },
    { 0x92, US_T },  { 0x2019, US_T },
    { 0x93, US_Q },  { 0x201C, US_Q },
    { 0x94, US_F },  { 0x201D, US_F },
    { 0x95, US_C },  { 0x2022, US_C },
    { 0x96, US_J },  { 0x2013, US_J },
    { 0x97, US_W },  { 0x2014, US_W },
    { 0x98, US_SET_INTERSECTION },
    { 0x99, US_SET_UNION },  { 0x2122, US_SET_UNION },
    { 0x9A, US_SUBSET },  { 0x0459, US_SUBSET },
    { 0x9B, US_NOTSUBSET },  { 0x203A, US_NOTSUBSET },
    { 0x9C, US_ELEMENT },  { 0x045A, US_ELEMENT },
    { 0x9D, US_NOTELEMENT },  { 0x045C, US_NOTELEMENT },
    { 0x9E, US_SUBSET_OR_EQ },  { 0x045B, US_SUBSET_OR_EQ },
    { 0x9F, US_NOTEQUAL },  { 0x045F, US_NOTEQUAL },

    { 0xA2, US_LOGIC_FORALL },  { 0x045E, US_LOGIC_FORALL },
    { 0xA3, US_MINUS },  { 0x0408, US_MINUS },

    { 0xA5, US_DIGIT_SUB0 },  { 0x0490, US_DIGIT_SUB0 },
    { 0xA6, US_DIGIT_SUB1 },
    { 0xA7, US_DIGIT_SUB2 },
    { 0xA8, US_DIGIT_SUB3 }, { 0x0401, US_DIGIT_SUB3 },
    { 0xA9, US_DIGIT_SUB4 },
    { 0xAA, US_DIGIT_SUB5 }, { 0x0404, US_DIGIT_SUB5 },
    { 0xAB, US_DIGIT_SUB6 },
    { 0xAC, US_DIGIT_SUB7 },
    { 0xAD, US_DIGIT_SUB8 },
    { 0xAE, US_DIGIT_SUB9 },
    { 0xAF, US_IDENTITY },  { 0x0407, US_IDENTITY },

    { 0xB1, US_IMPLICATION },
    { 0xB2, US_LOGIC_EQUAL },  { 0x0406, US_LOGIC_EQUAL },
    { 0xB3, US_LOGIC_NOT },  { 0x0456, US_LOGIC_NOT },
    { 0xB4, US_LOGIC_OR },  { 0x0491, US_LOGIC_OR },
    { 0xB5, US_CARTH },

    { 0xB7, US_SET_SYMMINUS },

    { 0xBA, US_INFINITY },  { 0x0454, US_INFINITY },
    { 0xBB, US_EMPTYSET },
    { 0xBC, US_BOOL },  { 0x0458, US_BOOL },
    { 0xBD, US_INTEGERS },  { 0x0405, US_INTEGERS },
    { 0xBE, US_NATURALS },  { 0x0455, US_NATURALS },
    { 0xBF, US_REALS },  { 0x0457, US_REALS }
  };
  if (!codeTable.contains(ac)) {
    return ac;
  } else {
    return codeTable.at(ac);
  }
}

} // namespace xtr::encode