/*  Sarien - A Sierra AGI resource interpreter engine
 *  Copyright (C) 1999,2001 Stuart George and Claudio Matsuoka
 *
 *  $Id: fileglob.c,v 1.3 2001/08/03 13:21:45 cmatsuoka Exp $
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; see docs/COPYING for further details.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <sys/types.h>
#include <dirent.h>

#include "sarien.h"
#include "agi.h"

#ifdef OPENVMS
static FILE *debug_fp = NULL;

static void debug_init(void) {
        /* Debug logging disabled for performance */
        return;
}

static void debug_log(const char *fmt, ...) {
        /* Debug logging disabled for performance */
        return;
}
#else
#define debug_log(...)
#endif


/* poor man's glob()
 *
 * For our needs, using glob() is overkill. Not all platforms have
 * glob, and glob performs case-sensitive matches we don't want.
 */
static char *match (char *p, int f)
{
        char *slash, *dir, *pattern, s[MAX_PATH];
        DIR *d;
        struct dirent *e;
        int i, j;
        static char path[MAX_PATH];
#ifdef OPENVMS
        static char vms_pattern[MAX_PATH];  /* Buffer to hold pattern for VMS paths */
#endif

        *path = 0;

        strcpy (s, p);
#ifdef OPENVMS
        /* OpenVMS: Handle VMS directory syntax [.subdir]filename */
        if (s[0] == '[') {
                char *rbracket = strchr(s, ']');
                if (rbracket) {
                        /* Save pattern to separate buffer before null-terminating */
                        strcpy(vms_pattern, rbracket + 1);
                        rbracket[1] = 0;  /* Null after ] so dir includes the bracket */
                        dir = s;
                        pattern = vms_pattern;
                } else {
                        /* No closing bracket, treat as Unix-style path */
                        slash = strrchr (s, '/');
                        if (slash) {
                                *slash = 0;
                                pattern = slash + 1;
                                dir = s;
                        } else {
                                pattern = s;
                                dir = ".";
                        }
                }
        } else
#endif
        {
                slash = strrchr (s, '/');
                if (slash) {
                        *slash = 0;
                        pattern = slash + 1;
                        dir = s;
                } else {
                        pattern = s;
                        dir = ".";
                }
        }

        _D ("dir=%s, pattern=%s", dir, pattern);

        /* empty pattern given */
        if (!*pattern)
                return NULL;

        if ((d = opendir (dir)) == NULL)
                return NULL;

#ifdef OPENVMS
        /* Strip VMS version number from pattern if present (e.g., KQ4VOL.0;1 -> KQ4VOL.0)
         * For VMS paths, pattern points to vms_pattern buffer which we can modify directly */
        {
                int pattern_len = strlen(pattern);
                int orig_len = pattern_len;
                char pattern_copy[MAX_PATH];
                strcpy(pattern_copy, pattern);

                while (pattern_len > 0 && pattern[pattern_len-1] >= '0' && pattern[pattern_len-1] <= '9')
                        pattern_len--;
                if (pattern_len > 0 && pattern[pattern_len-1] == ';') {
                        if (pattern_len > 1 && pattern[pattern_len-2] == '.') {
                                pattern_len -= 2;
                        } else {
                                pattern_len--;
                        }
                        /* Directly truncate the pattern string (works for both vms_pattern and s-based patterns) */
                        ((char*)pattern)[pattern_len] = '\0';
                        debug_log("DEBUG: Pattern '%s' stripped to '%s' (length %d, was %d)\n",
                                pattern_copy, pattern, pattern_len, orig_len);
                }
        }
        /* j will be set inside the loop for each file */
        if (strncasecmp(pattern, "object", 6) == 0) {
                debug_log("DEBUG: After pattern strip, j=%d, strlen(pattern)=%d, pattern='%s'\n",
                        -1, strlen(pattern), pattern);
        }
#else
        /* j will be set inside the loop for each file */
#endif

        while ((e = readdir (d)) != NULL) {
                int j = strlen (pattern) - 1;  /* Reset j for each file */
                /* check backwards */
                i = strlen (e->d_name) - 1;

#ifdef OPENVMS
                /* Strip VMS version number (;1, ;2, etc.) for comparison
                 * Context-aware stripping based on pattern:
                 * - If pattern ends with '.': strip only ;N (match "kq4dir." to "KQ4DIR.;1" → "KQ4DIR.")
                 * - If pattern has no trailing '.': strip .;N (match "object" to "OBJECT.;1" → "OBJECT")
                 * - Files with real extensions: always strip only ;N (match "vol.0" to "VOL.0;1" → "VOL.0")
                 */
                {
                        int save_pos = i;
                        int orig_i = i;
                        int pattern_len = strlen(pattern);
                        int pattern_ends_with_dot = (pattern_len > 0 && pattern[pattern_len-1] == '.');

                        /* Skip version number digits */
                        while (i >= 0 && e->d_name[i] >= '0' && e->d_name[i] <= '9')
                                i--;
                        /* Found semicolon? */
                        if (i >= 0 && e->d_name[i] == ';') {
                                /* Check if there's a dot right before the semicolon */
                                if (i > 0 && e->d_name[i-1] == '.') {
                                        /* File has form FILENAME.;1 (extensionless on VMS) */
                                        if (pattern_ends_with_dot) {
                                                /* Pattern wants the dot: strip only ;1 */
                                                i--;
                                                debug_log( "DEBUG: File '%s' pattern ends with dot -> keep dot, stripped to length %d\n",
                                                        e->d_name, i+1);
                                        } else {
                                                /* Pattern has no dot: strip .;1 */
                                                i -= 2;
                                                debug_log( "DEBUG: File '%s' pattern has no dot -> strip dot too, stripped to length %d\n",
                                                        e->d_name, i+1);
                                        }
                                } else {
                                        /* File has real extension: KQ4VOL.0;1 - just strip ;1 */
                                        i--;
                                        debug_log( "DEBUG: File '%s' -> has extension, stripped to length %d (was %d)\n",
                                                e->d_name, i+1, orig_i+1);
                                }
                        } else {
                                /* No version number found, restore position */
                                i = save_pos;
                                /* But also check for trailing dot (readdir may have stripped version) */
                                if (i >= 0 && e->d_name[i] == '.' && !pattern_ends_with_dot) {
                                        /* kq4dir. case but pattern doesn't want dot - strip it */
                                        i--;
                                        debug_log( "DEBUG: File '%s' -> stripped trailing dot, length %d (was %d)\n",
                                                e->d_name, i+1, orig_i+1);
                                }
                        }
                }
#endif

                /* j is already set at top of loop */
                for (; i >= 0 && j >= 0; i--, j--) {
                        if (pattern[j] == '*') {
                                i = j = -1;
                                break;
                        }
                        if (tolower (e->d_name[i]) != tolower (pattern[j]))
                                break;
                }

                /* exact match */
                if (i < 0 && j <= 0) {
#ifdef OPENVMS
                        debug_log( "DEBUG match(): FOUND '%s' matches pattern '%s'\n", e->d_name, pattern);
#endif
                        if (f) {
                                strcpy (path, dir);
#ifdef OPENVMS
                                /* OpenVMS: For VMS directory syntax [.subdir], append filename directly without '/' */
                                if (dir[0] == '[' && dir[strlen(dir)-1] == ']') {
                                        /* VMS directory format - no separator needed */
                                        /* Strip version number from filename for fopen() compatibility */
                                        int name_len = strlen(e->d_name);
                                        int save_len = name_len;
                                        char stripped_name[MAX_PATH];
                                        strcpy(stripped_name, e->d_name);

                                        /* Strip ;N version - also strip dot before ; for extensionless files */
                                        while (name_len > 0 && stripped_name[name_len-1] >= '0' && stripped_name[name_len-1] <= '9')
                                                name_len--;
                                        if (name_len > 0 && stripped_name[name_len-1] == ';') {
                                                /* Found version number - strip it */
                                                name_len--;
                                                stripped_name[name_len] = 0;
                                                /* Also strip trailing dot if present (extensionless files) */
                                                if (name_len > 0 && stripped_name[name_len-1] == '.') {
                                                        name_len--;
                                                        stripped_name[name_len] = 0;
                                                }
                                        } else {
                                                /* No version number - restore original position */
                                                name_len = save_len;
                                        }

                                        strcat (path, stripped_name);
                                        debug_log( "DEBUG match(): VMS path constructed: '%s' (from '%s')\n", path, e->d_name);
                                } else
#endif
                                {
                                        strcat (path, "/");
#ifdef OPENVMS
                                        /* OpenVMS: Strip version and trailing dot for extensionless files */
                                        int name_len = strlen(e->d_name);
                                        int save_len = name_len;
                                        char stripped_name[MAX_PATH];
                                        strcpy(stripped_name, e->d_name);

                                        /* Strip ;N version */
                                        while (name_len > 0 && stripped_name[name_len-1] >= '0' && stripped_name[name_len-1] <= '9')
                                                name_len--;
                                        if (name_len > 0 && stripped_name[name_len-1] == ';') {
                                                name_len--;
                                                stripped_name[name_len] = 0;
                                                /* Also strip trailing dot (for extensionless files) */
                                                if (name_len > 0 && stripped_name[name_len-1] == '.') {
                                                        name_len--;
                                                        stripped_name[name_len] = 0;
                                                }
                                        } else {
                                                name_len = save_len;
                                        }

                                        strcat(path, stripped_name);
#else
                                        strcat (path, e->d_name);
#endif
                                }
                        } else {
#ifdef OPENVMS
                                /* Strip version and trailing dot for extensionless files */
                                int name_len = strlen(e->d_name);
                                int save_len = name_len;
                                char stripped_name[MAX_PATH];
                                strcpy(stripped_name, e->d_name);

                                /* Strip ;N version */
                                while (name_len > 0 && stripped_name[name_len-1] >= '0' && stripped_name[name_len-1] <= '9')
                                        name_len--;
                                if (name_len > 0 && stripped_name[name_len-1] == ';') {
                                        /* Found version number - strip it */
                                        name_len--;
                                        stripped_name[name_len] = 0;
                                        /* Also strip trailing dot (for extensionless files) */
                                        if (name_len > 0 && stripped_name[name_len-1] == '.') {
                                                name_len--;
                                                stripped_name[name_len] = 0;
                                        }
                                } else {
                                        /* No version number - restore original position */
                                        name_len = save_len;
                                }

                                strcpy (path, stripped_name);
#else
                                strcpy (path, e->d_name);
#endif
                        }
                        return path;
                }
        }

#ifdef OPENVMS
        debug_log( "DEBUG match(): NOT FOUND (searched %s for %s)\n", dir, pattern);
#endif
        return NULL;
}


int file_isthere (char *fname)
{
        _D ("(fname=%s)", fname);
        return match (fname, 0) != NULL;
}


char* file_name (char *fname)
{
        _D ("(fname=%s)", fname);
        return match (fname, 0);
}


char *fixpath (int flag, char *fname)
{
        static char path[MAX_PATH];
        char *s;

        _D ("(flag = %d, fname = \"%s\")", flag, fname);
        _D ("game.dir = %s", game.dir);

#ifdef OPENVMS
        debug_log( "DEBUG fixpath(): flag=%d, fname='%s', game.dir='%s', game.name='%s'\n",
                flag, fname, game.dir, game.name);
#endif

        strcpy (path, game.dir);
#ifdef OPENVMS
        /* OpenVMS: For VMS directory [.subdir], don't add '/' separator */
        if (*path && path[strlen (path) - 1] != '/' && path[strlen (path) - 1] != ']')
#else
        if (*path && path[strlen (path) - 1] != '/')
#endif
                strcat (path, "/");
        if (flag)
                strcat (path, game.name);

        strcat (path, fname);

#ifndef OPENVMS
        /* Don't strip trailing dot on OpenVMS - the match() function handles
         * VMS file versioning and will match "dir." to "DIR.;1" correctly */
        if (path[strlen (path) - 1] == '.')
                path[strlen (path) - 1] = 0;
#endif
        _D ("path = %s", path);

        if ((s = match (path, 1)) != NULL) {
                strcpy (path, s);
        } else {
                /* For amiga games */
                strcat (path, "s");
                if ((s = match (path, 1)) != NULL) {
                        strcpy (path, s);
                } else {
#ifdef OPENVMS
                        debug_log( "DEBUG: File not found, searched for: %s\n", path);
#endif
                        path[0] = 0;
                }
        }

        _D ("fixed path = %s", path);

        return path;
}


char *get_current_directory ()
{
        return (".");
}

