/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2018 Red Hat, Inc.
 */

#ifndef __NM_SETTINGS_STORAGE_H__
#define __NM_SETTINGS_STORAGE_H__

/*****************************************************************************/

#include "c-list/src/c-list.h"

#define NM_TYPE_SETTINGS_STORAGE (nm_settings_storage_get_type())
#define NM_SETTINGS_STORAGE(obj) \
    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTINGS_STORAGE, NMSettingsStorage))
#define NM_SETTINGS_STORAGE_CLASS(klass) \
    (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTINGS_STORAGE, NMSettingsStorageClass))
#define NM_IS_SETTINGS_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTINGS_STORAGE))
#define NM_IS_SETTINGS_STORAGE_CLASS(klass) \
    (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTINGS_STORAGE))
#define NM_SETTINGS_STORAGE_GET_CLASS(obj) \
    (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTINGS_STORAGE, NMSettingsStorageClass))

#define NM_SETTINGS_STORAGE_PLUGIN   "plugin"
#define NM_SETTINGS_STORAGE_UUID     "uuid"
#define NM_SETTINGS_STORAGE_FILENAME "filename"

struct _NMSettingsPlugin;

/**
 * NMSettingsStorage:
 * @_plugin: The settings plugin that provides this storage.
 * @_uuid: UUID of the profile represented by this storage.
 * @_filename: Backing filename (can be NULL for in-memory or meta-data).
 * @_storage_lst: Node in the per-plugin storage list.
 * @_storage_by_uuid_lst: Node in the per-UUID storage list.
 *
 * Describes the origin and identity of one profile instance as provided by a
 * specific settings plugin and (optionally) a backing file. A single UUID may
 * have multiple storages from different plugins; plugin order determines
 * priority.
 */
typedef struct NMSettingsStorage {
    GObject                   parent;
    struct _NMSettingsPlugin *_plugin;
    char                     *_uuid;
    char                     *_filename;
    CList                     _storage_lst;
    CList                     _storage_by_uuid_lst;
} NMSettingsStorage;

typedef struct {
    GObjectClass parent;

    int (*cmp_fcn)(NMSettingsStorage *a, NMSettingsStorage *b);

} NMSettingsStorageClass;

GType nm_settings_storage_get_type(void);

NMSettingsStorage *
nm_settings_storage_new(struct _NMSettingsPlugin *plugin, const char *uuid, const char *filename);

/* forward declare so we don't have to include "nm-settings-plugin.h" here. */
GType nm_settings_plugin_get_type(void);

static inline struct _NMSettingsPlugin *
nm_settings_storage_get_plugin(const NMSettingsStorage *self)
{
    g_return_val_if_fail(NM_IS_SETTINGS_STORAGE(self), NULL);

    nm_assert(G_TYPE_CHECK_INSTANCE_TYPE(self->_plugin, nm_settings_plugin_get_type()));
    return self->_plugin;
}

gboolean nm_uuid_is_normalized_full(const char *str);

static inline const char *
nm_settings_storage_get_uuid(const NMSettingsStorage *self)
{
    g_return_val_if_fail(NM_IS_SETTINGS_STORAGE(self), NULL);

    nm_assert(nm_uuid_is_normalized_full(self->_uuid));
    return self->_uuid;
}

static inline const char *
nm_settings_storage_get_uuid_opt(const NMSettingsStorage *self)
{
    g_return_val_if_fail(NM_IS_SETTINGS_STORAGE(self), NULL);

    nm_assert(!self->_uuid || nm_uuid_is_normalized_full(self->_uuid));
    return self->_uuid;
}

static inline const char *
nm_settings_storage_get_filename(const NMSettingsStorage *self)
{
    g_return_val_if_fail(NM_IS_SETTINGS_STORAGE(self), NULL);

    return self->_filename;
}

/*****************************************************************************/

#define nm_assert_valid_settings_storage(plugin, storage)                           \
    G_STMT_START                                                                    \
    {                                                                               \
        NMSettingsPlugin *const  _plugin  = (plugin);                               \
        NMSettingsStorage *const _storage = (storage);                              \
                                                                                    \
        nm_assert(!_plugin || NM_IS_SETTINGS_PLUGIN(_plugin));                      \
        nm_assert(NM_IS_SETTINGS_STORAGE(_storage));                                \
        nm_assert(!_plugin || nm_settings_storage_get_plugin(_storage) == _plugin); \
    }                                                                               \
    G_STMT_END

/*****************************************************************************/

int nm_settings_storage_cmp(NMSettingsStorage *sd_a,
                            NMSettingsStorage *sd_b,
                            const GSList      *plugin_list);

#endif /* __NM_SETTINGS_STORAGE_H__ */
