#include <algorithm>
#include <iostream>
#include <locale.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
// #include <stringapiset.h>
#include <tchar.h>
// #include <wchar.h>
#include <windows.h>

void reverse_file(const char *input_filename, const char *output_filename);
void reverse_string(char *str, size_t len, int codepage);
int get_codepage(const char *filename);

int main() {
  // Зміна локалізації на українську для сумісності з UNICODE
  // setlocale(LC_ALL, "Ukrainian");
  // Зміна кодової сторінки консолі на 1251 для сумісності з ASCII
  SetConsoleOutputCP(1251);
  SetConsoleCP(1251);

  int tchar_size = sizeof(TCHAR);
  printf("TCHAR size: %d\n", tchar_size);

  char ua_strings[3][60] = {"Ситник Сергій Олексійович",
                            "Ситник Єгор Сергійович",
                            "Ситник Ольга Володимирівна"};

  printf("\nua_strings:\n");
  for (int i = 0; i < 3; i++) {
    printf("%d: %s\n", i + 1, ua_strings[i]);
  }

  printf("\nua_wstrings:\n");
  wchar_t ua_wstrings[3][60] = {};
  for (int i = 0; i < 3; i++) {
    MultiByteToWideChar(CP_ACP, 0, ua_strings[i], -1, ua_wstrings[i], 60);

    printf("- - - - - - - - - - - - - - - - - - - - - -\n");
    printf("%d:\n", i + 1);

    _tprintf(_T("_tprintf:\t%ls\n"), ua_wstrings[i]);
    std::wcout << L"std::wcout:\t" << ua_wstrings[i] << std::endl;
    MessageBoxW(NULL, ua_wstrings[i], L"MessageBox", MB_OK);
  }

  // Копіювання масиву рядків для перевірки сортування
  wchar_t ua_wstrings_to_qsort[3][60] = {};
  wchar_t *ua_wstrings_to_sort[3] = {};
  for (int i = 0; i < 3; i++) {
    // Копіювання масиву для qsort
    wcscpy(ua_wstrings_to_qsort[i], ua_wstrings[i]);

    // Копіювання масиву для std::sort
    ua_wstrings_to_sort[i] = (wchar_t *)malloc(sizeof(wchar_t) * 60);
    wcscpy(ua_wstrings_to_sort[i], ua_wstrings[i]);
  }

  printf("\nqsort:\n");
  qsort(ua_wstrings_to_qsort, 3, sizeof(wchar_t) * 60,
        (int (*)(const void *, const void *))wcscoll);

  for (int i = 0; i < 3; i++) {
    _tprintf(_T("%ls\n"), ua_wstrings_to_qsort[i]);
  }

  printf("\nstd::sort:\n");
  std::sort(ua_wstrings_to_sort, ua_wstrings_to_sort + 3,
            [](const wchar_t *a, const wchar_t *b) -> bool {
              return wcscoll(a, b) < 0;
            });
  for (int i = 0; i < 3; i++) {
    _tprintf(_T("%ls\n"), ua_wstrings_to_sort[i]);
  }

  printf("\nua_strings_from_wstrings:\n");
  char ua_strings_from_wstrings[3][60] = {};
  for (int i = 0; i < 3; i++) {
    WideCharToMultiByte(CP_ACP, 0, ua_wstrings[i], -1,
                        ua_strings_from_wstrings[i], 60, NULL, NULL);

    printf("%d: %s\n", i + 1, ua_strings_from_wstrings[i]);
  }

  printf("\nfile convertions:\n");
  reverse_file("inputA.txt", "outputA.txt");
  reverse_file("inputU.txt", "outputU.txt");

  return 0;
}

void reverse_string(char *str, size_t len, int codepage) {
  if (str == NULL || len == 0)
    return;

  wchar_t *wstr = (wchar_t *)malloc(sizeof(wchar_t) * (len + 1));
  if (wstr == NULL) {
    fprintf(stderr, "Error encountered while allocating memory\n");
    return;
  }

  MultiByteToWideChar(codepage, 0, str, len + 1, wstr, len + 1);
  size_t wlen = wcslen(wstr);

  for (size_t i = 0, j = wlen - 1; i < j; i++, j--) {
    wchar_t temp = wstr[i];
    wstr[i] = wstr[j];
    wstr[j] = temp;
  }

  WideCharToMultiByte(codepage, 0, wstr, len, str, len, NULL, NULL);

  free(wstr);
}

void reverse_file(const char *input_filename, const char *output_filename) {
  FILE *input_file = fopen(input_filename, "r");
  if (input_file == NULL) {
    fprintf(stderr, "Cant open input file '%s'\n", input_filename);
    return;
  }

  FILE *output_file = fopen(output_filename, "w");
  if (output_file == NULL) {
    fprintf(stderr, "Cant create output file '%s'\n", output_filename);
    fclose(input_file);
    return;
  }

  int codepage = get_codepage(input_filename);

  char buffer[4096];

  while (fgets(buffer, sizeof(buffer), input_file) != NULL) {
    size_t len = strlen(buffer);

    if (len > 0 && buffer[len - 1] == '\n') {
      buffer[len - 1] = '\0';
      len--;
    }

    reverse_string(buffer, len, codepage);

    fprintf(output_file, "%s\n", buffer);
  }

  fclose(input_file);
  fclose(output_file);

  printf("Successfully reversed file '%s' to '%s'\n", input_filename,
         output_filename);
};

int get_codepage(const char *filename) {
  FILE *file = fopen(filename, "r");
  if (file == NULL) {
    fprintf(stderr, "Cant open file '%s'\n", filename);
    return -1;
  }

  int codepage;

  if (fgetc(file) == 0xEF && fgetc(file) == 0xBB && fgetc(file) == 0xBF) {
    codepage = CP_UTF8;
  } else {
    codepage = CP_ACP;
  }

  fclose(file);

  return codepage;
}
