/* SPDX-License-Identifier: LGPL-2.1-or-later */

#include "errno-util.h"
#include "kbd-util.h"
#include "log.h"
#include "nulstr-util.h"
#include "path-util.h"
#include "recurse-dir.h"
#include "set.h"
#include "string-util.h"
#include "strv.h"
#include "utf8.h"

struct recurse_dir_userdata {
        const char *keymap_name;
        Set *keymaps;
};

static int keymap_recurse_dir_callback(
                RecurseDirEvent event,
                const char *path,
                int dir_fd,
                int inode_fd,
                const struct dirent *de,
                const struct statx *sx,
                void *userdata) {

        struct recurse_dir_userdata *data = userdata;
        _cleanup_free_ char *p = NULL;
        int r;

        assert(de);

        /* If 'keymap_name' is non-NULL, return true if keymap 'keymap_name' is found.  Otherwise, add all
         * keymaps to 'keymaps'. */

        if (event != RECURSE_DIR_ENTRY)
                return RECURSE_DIR_CONTINUE;

        if (!IN_SET(de->d_type, DT_REG, DT_LNK))
                return RECURSE_DIR_CONTINUE;

        const char *e = endswith(de->d_name, ".map") ?: endswith(de->d_name, ".map.gz");
        if (!e)
                return RECURSE_DIR_CONTINUE;

        p = strndup(de->d_name, e - de->d_name);
        if (!p)
                return -ENOMEM;

        if (data->keymap_name)
                return streq(p, data->keymap_name) ? 1 : RECURSE_DIR_CONTINUE;

        assert(data->keymaps);

        if (!keymap_is_valid(p))
                return 0;

        r = set_consume(data->keymaps, TAKE_PTR(p));
        if (r < 0)
                return r;

        return RECURSE_DIR_CONTINUE;
}

int get_keymaps(char ***ret) {
        _cleanup_(set_free_freep) Set *keymaps = NULL;
        int r;

        keymaps = set_new(&string_hash_ops);
        if (!keymaps)
                return -ENOMEM;

        NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) {
                r = recurse_dir_at(
                                AT_FDCWD,
                                dir,
                                /* statx_mask= */ 0,
                                /* n_depth_max= */ UINT_MAX,
                                RECURSE_DIR_IGNORE_DOT|RECURSE_DIR_ENSURE_TYPE,
                                keymap_recurse_dir_callback,
                                &(struct recurse_dir_userdata) {
                                        .keymaps = keymaps,
                                });
                if (r < 0) {
                        if (r == -ENOENT)
                                continue;
                        if (ERRNO_IS_RESOURCE(r))
                                return log_warning_errno(r, "Failed to read keymap list from %s: %m", dir);

                        log_debug_errno(r, "Failed to read keymap list from %s, ignoring: %m", dir);
                }
        }

        _cleanup_strv_free_ char **l = set_get_strv(keymaps);
        if (!l)
                return -ENOMEM;

        keymaps = set_free(keymaps); /* If we got the strv above, then do a set_free() rather than
                                      * set_free_free() since the entries of the set are now owned by the
                                      * strv */

        if (strv_isempty(l))
                return -ENOENT;

        strv_sort(l);

        *ret = TAKE_PTR(l);
        return 0;
}

bool keymap_is_valid(const char *name) {
        if (isempty(name))
                return false;

        if (strlen(name) >= 128)
                return false;

        if (!utf8_is_valid(name))
                return false;

        if (!filename_is_valid(name))
                return false;

        if (!string_is_safe(name))
                return false;

        return true;
}

int keymap_exists(const char *name) {
        int r = 0;

        if (!keymap_is_valid(name))
                return -EINVAL;

        NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) {
                r = recurse_dir_at(
                                AT_FDCWD,
                                dir,
                                /* statx_mask= */ 0,
                                /* n_depth_max= */ UINT_MAX,
                                RECURSE_DIR_IGNORE_DOT|RECURSE_DIR_ENSURE_TYPE,
                                keymap_recurse_dir_callback,
                                &(struct recurse_dir_userdata) {
                                        .keymap_name = name,
                                });
                if (r == -ENOENT)
                        continue;
                if (ERRNO_IS_RESOURCE(r))
                        return r;
                if (r < 0) {
                        log_debug_errno(r, "Failed to read keymap list from %s, ignoring: %m", dir);
                        continue;
                }
                if (r > 0)
                        break;
        }

        return r > 0;
}
