// SPDX-License-Identifier: GPL-3.0-or-later

#include <stdio.h>
#include <glob.h>
#include <string.h>
#include <stdlib.h>

#include "util.h"
#include "glob_portable.h"

pattern_list expand_brace_pattern(const char *pattern) {
    pattern_list list = {NULL, 0};
    const char *open = strchr(pattern, '{');
    const char *close = open ? strchr(pattern, '}') : NULL;

    if (!open || !close) {
        list.patterns = malloc(sizeof(char*));
        list.patterns[0] = xstrdup(pattern);
        list.count = 1;
        return list;
    }

    char *brace = xstrndup(open+1, close-open-1);
    char *prefix = xstrndup(pattern, open-pattern);
    char *suffix = xstrdup(close+1);

    size_t comma_count = 1;
    for (char *p = brace; *p; p++) {
        if (*p == ',')
            comma_count++;
    }

    list.patterns = malloc(comma_count*sizeof(char*));
    list.count = comma_count;

    char *saveptr;
    char *token = strtok_r(brace, ",", &saveptr);
    size_t i = 0;
    while (token && i < comma_count) {
        size_t len = strlen(prefix) + strlen(token) + strlen(suffix) + 1;
        list.patterns[i] = malloc(len);
        snprintf(list.patterns[i], len, "%s%s%s", prefix, token, suffix);
        i++;
        token = strtok_r(NULL, ",", &saveptr);
    }

    free(brace);
    free(prefix);
    free(suffix);
    return list;
}

int glob_brace(const char *pattern, glob_t *pglob, int flags,
               int (*errfunc)(const char *epath, int eerrno)) {
    pattern_list patterns = expand_brace_pattern(pattern);

    int result = GLOB_NOMATCH;

    for (size_t i = 0; i < patterns.count; i++) {
        if (i == 0) {
            result = glob(patterns.patterns[i], flags, errfunc, pglob);
        } else {
            result = glob(patterns.patterns[i], flags | GLOB_APPEND, errfunc, pglob);
        }
        free(patterns.patterns[i]);
    }
    free(patterns.patterns);

    return result;
}
