/* TCHCONV.C - The Cat Help Converter V2.0 (Win95/Win32 Optimized) */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* --- GLOBALS & HELPERS --- */

/* Prüft, ob Datei existiert */
int FileExists(char* path) {
    DWORD attr = GetFileAttributes(path);
    return (attr != 0xFFFFFFFF && !(attr & FILE_ATTRIBUTE_DIRECTORY));
}

/* UTF-8 <-> ANSI Konverter (Bleibt gleich, da Win32 API hier perfekt ist) */
void Utf8ToAnsi(const char* src, char* dst, int maxLen) {
    int len = MultiByteToWideChar(CP_UTF8, 0, src, -1, NULL, 0);
    WCHAR* wBuf = (WCHAR*)malloc(len * sizeof(WCHAR));
    if(!wBuf) return;
    MultiByteToWideChar(CP_UTF8, 0, src, -1, wBuf, len);
    WideCharToMultiByte(CP_ACP, 0, wBuf, -1, dst, maxLen, NULL, NULL);
    free(wBuf);
}

void AnsiToUtf8(const char* src, char* dst, int maxLen) {
    int len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
    WCHAR* wBuf = (WCHAR*)malloc(len * sizeof(WCHAR));
    if(!wBuf) return;
    MultiByteToWideChar(CP_ACP, 0, src, -1, wBuf, len);
    WideCharToMultiByte(CP_UTF8, 0, wBuf, -1, dst, maxLen, NULL, NULL);
    free(wBuf);
}

/* --- NAMENSGENERIERUNG (DAS KOMFORT-FEATURE) --- */

/* Generiert intelligenten 8.3 Namen: LongFile.tchelp -> LONGFIL~1.TCH */
void GenerateDosName(char* inPath, char* outPath) {
    char drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT];
    char base[9];
    int i, j, counter = 1;

    /* Pfad zerlegen (Standard C Lib, sicher in VC6) */
    _splitpath(inPath, drive, dir, fname, ext);

    /* Basis bereinigen (Nur A-Z, 0-9) und Uppercase */
    j = 0;
    for(i=0; i<strlen(fname) && j<6; i++) {
        char c = toupper(fname[i]);
        if ((c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) {
            base[j++] = c;
        }
    }
    base[j] = 0;
    if (strlen(base) == 0) strcpy(base, "FILE");

    /* Kollisionsprüfung: Zähle ~1, ~2 hoch bis frei */
    do {
        char num[10];
        wsprintf(num, "~%d", counter);
        
        strcpy(outPath, drive);
        strcat(outPath, dir);
        strcat(outPath, base);
        strcat(outPath, num);
        strcat(outPath, ".TCH");
        
        counter++;
    } while (FileExists(outPath) && counter < 100);
}

/* Generiert Win Namen: FILE~1.TCH -> File~1.tchelp (Simple Umbenennung) */
void GenerateWinName(char* inPath, char* outPath) {
    char drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT];
    
    _splitpath(inPath, drive, dir, fname, ext);
    
    /* Wir ändern nur die Endung. Den Namen schön zu machen (TitleCase) 
       ist ohne Wörterbuch schwer, wir belassen ihn im Original */
    
    strcpy(outPath, drive);
    strcat(outPath, dir);
    strcat(outPath, fname);
    strcat(outPath, ".tchelp");
}

/* --- KONVERTIERUNGSLOGIK --- */

int ConvertFileContent(char* inFile, char* outFile, int toWin) {
    FILE *fin, *fout;
    char *inBuf, *outBuf;
    long fsize;

    fin = fopen(inFile, "rb");
    if (!fin) return 0;

    fseek(fin, 0, SEEK_END); fsize = ftell(fin); fseek(fin, 0, SEEK_SET);
    
    inBuf = (char*)malloc(fsize + 1);
    outBuf = (char*)malloc((fsize * 2) + 1); /* Puffer für UTF-8 Expansion */
    
    if (!inBuf || !outBuf) { fclose(fin); return 0; }

    fread(inBuf, 1, fsize, fin);
    inBuf[fsize] = 0;
    fclose(fin);

    if (toWin) AnsiToUtf8(inBuf, outBuf, fsize * 2);
    else Utf8ToAnsi(inBuf, outBuf, fsize * 2);

    fout = fopen(outFile, "wb");
    if (fout) {
        fwrite(outBuf, 1, strlen(outBuf), fout);
        fclose(fout);
        printf("  [OK] %s -> %s\n", inFile, outFile);
    } else {
        printf("  [ERR] Write failed: %s\n", outFile);
    }

    free(inBuf); free(outBuf);
    return 1;
}

/* Wrapper für Wildcard-Verarbeitung */
void ProcessFiles(char* inputPattern, int toWin) {
    WIN32_FIND_DATA fd;
    HANDLE hFind;
    char searchPath[MAX_PATH];
    char inPath[MAX_PATH];
    char outPath[MAX_PATH];
    char folder[MAX_PATH];
    char* p;

    /* Ordner extrahieren um korrekte Pfade zu bauen */
    strcpy(folder, inputPattern);
    p = strrchr(folder, '\\');
    if (p) *(p+1) = 0; /* "C:\Test\" behalten */
    else folder[0] = 0; /* Aktueller Ordner */

    hFind = FindFirstFile(inputPattern, &fd);
    if (hFind == INVALID_HANDLE_VALUE) {
        printf("Keine Dateien gefunden fuer: %s\n", inputPattern);
        return;
    }

    do {
        if (strcmp(fd.cFileName, ".") == 0 || strcmp(fd.cFileName, "..") == 0) continue;
        if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;

        wsprintf(inPath, "%s%s", folder, fd.cFileName);
        
        /* Automatische Ziel-Namensgebung */
        if (toWin) GenerateWinName(inPath, outPath);
        else GenerateDosName(inPath, outPath);

        ConvertFileContent(inPath, outPath, toWin);

    } while (FindNextFile(hFind, &fd));

    FindClose(hFind);
}

/* --- PROJEKT LOGIK (Inkl. Namensanpassung in der Datei) --- */

void ConvertProject(char* inFile, char* outFile, int toWin) {
    FILE *fin, *fout;
    char line[1024];
    char entryName[MAX_PATH];
    char outName[MAX_PATH];

    fin = fopen(inFile, "r");
    if (!fin) { printf("Projektdatei nicht gefunden.\n"); return; }
    fout = fopen(outFile, "w");
    if (!fout) { fclose(fin); return; }

    printf("Konvertiere Projekt: %s -> %s\n", inFile, outFile);

    if (!toWin) {
        /* XML -> FLAT (.tcp) */
        /* Wir müssen die 8.3 Namen berechnen, die ProcessFiles erstellt hätte! */
        /* HINWEIS: Das ist tricky. Hier simulieren wir die 8.3 Logik ohne Dateicheck */
        while(fgets(line, 1023, fin)) {
            char* start = strstr(line, "<file>");
            if (start) {
                char* end = strstr(start, "</file>");
                if (end) {
                    *end = 0;
                    strcpy(entryName, start + 6);
                    
                    /* Pfad bereinigen */
                    { char* s=entryName; while(*s){if(*s=='/')*s='\\'; s++;} }
                    
                    /* 8.3 Generieren (Simpel, da wir Datei nicht checken können) */
                    GenerateDosName(entryName, outName);
                    
                    /* Nur Dateiname ins TCP schreiben (DOS Style) */
                    {
                         char* p = strrchr(outName, '\\');
                         fprintf(fout, "%s\n", p ? p+1 : outName);
                    }
                }
            }
        }
    } else {
        /* FLAT -> XML (.tcproject) */
        fprintf(fout, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
        fprintf(fout, "<tcproject name=\"Imported\">\n");
        while(fgets(line, 1023, fin)) {
            line[strcspn(line, "\r\n")] = 0;
            if (strlen(line) > 0) {
                /* Endung tauschen */
                GenerateWinName(line, outName);
                /* Pfad normalisieren für XML */
                { char* s=outName; while(*s){if(*s=='\\')*s='/'; s++;} }
                /* Nur Dateiname nehmen */
                {
                    char* p = strrchr(outName, '/');
                    fprintf(fout, "  <file>%s</file>\n", p ? p+1 : outName);
                }
            }
        }
        fprintf(fout, "</tcproject>\n");
    }

    fclose(fin);
    fclose(fout);
    printf("Projekt Konvertierung fertig.\n");
}

int main(int argc, char* argv[]) {
    if (argc < 3) {
        printf("TCHCONV v2.0 - Batch Converter\n");
        printf("Usage: tchconv <mode> <input> [output]\n");
        printf("Modes:\n");
        printf("  -f2dos   Files: *.tchelp -> 8.3 .TCH (UTF8 to ANSI)\n");
        printf("  -f2win   Files: *.TCH -> .tchelp (ANSI to UTF8)\n");
        printf("  -p2dos   Proj:  project.tcproject -> list.tcp\n");
        printf("  -p2win   Proj:  list.tcp -> project.tcproject\n");
        return 0;
    }

    /* Modus erkennen */
    if (strcmp(argv[1], "-f2dos") == 0) {
        ProcessFiles(argv[2], 0);
    }
    else if (strcmp(argv[1], "-f2win") == 0) {
        ProcessFiles(argv[2], 1);
    }
    else if (strcmp(argv[1], "-p2dos") == 0) {
        char out[MAX_PATH];
        if (argc > 3) strcpy(out, argv[3]); else strcpy(out, "PROJECT.TCP");
        ConvertProject(argv[2], out, 0);
    }
    else if (strcmp(argv[1], "-p2win") == 0) {
        char out[MAX_PATH];
        if (argc > 3) strcpy(out, argv[3]); else strcpy(out, "Project.tcproject");
        ConvertProject(argv[2], out, 1);
    }
    else {
        printf("Unbekannter Befehl.\n");
    }

    return 0;
}