/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
 *
 * Copyright © 2025 GNOME Foundation, Inc.
 *
 * SPDX-License-Identifier: LGPL-2.1-or-later
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Authors:
 *  - Philip Withnall <pwithnall@gnome.org>
 */

#pragma once

#include <gio/gio.h>
#include <glib.h>
#include <glib-object.h>

G_BEGIN_DECLS

/**
 * MctWebFilterType:
 * @MCT_WEB_FILTER_TYPE_NONE: The user’s web access is not filtered.
 * @MCT_WEB_FILTER_TYPE_BLOCKLIST: Websites are allowed by default unless
 *   they’re listed in one of the block lists or the custom block list. The
 *   allow lists and custom allow list override the block lists.
 * @MCT_WEB_FILTER_TYPE_ALLOWLIST: Websites are blocked by default unless
 *   they’re listed in one of the allow lists or the custom allow list. The
 *   block lists are ignored.
 *
 * Types of web filtering which can be imposed on an account.
 *
 * Additional types may be added in future.
 *
 * Since: 0.14.0
 */
typedef enum
{
  /* these values are used in the org.freedesktop.Malcontent.WebFilter
   * D-Bus interface, so must not be changed */
  MCT_WEB_FILTER_TYPE_NONE = 0,
  MCT_WEB_FILTER_TYPE_BLOCKLIST = 1,
  MCT_WEB_FILTER_TYPE_ALLOWLIST = 2,
} MctWebFilterType;

/**
 * MctWebFilter:
 *
 * [struct@Malcontent.WebFilter] is an opaque, immutable structure which
 * contains a snapshot of the web filter settings for a user at a given time.
 *
 * This includes whether web access is being filtered, and the filter lists
 * which are being applied — for example, the domains to block or allow.
 *
 * Typically, web filter settings can only be changed by the administrator,
 * and are read-only for non-administrative users. The precise policy is set
 * using polkit.
 *
 * To construct a new [struct@Malcontent.WebFilter], use
 * [struct@Malcontent.WebFilterBuilder].
 *
 * ## Filter format
 *
 * A web filter contains various high-level options about web filter, such as
 * whether to block domains by default or to allow them by default; and whether
 * to force popular websites to use their ‘safe search’ variants (for example,
 * Google Safe Search or YouTube Restricted Mode).
 *
 * A web filter can contain zero or more filter lists, as well as custom filter
 * entries. Each list or entry will block or allow the hostnames it lists.
 *
 * The intention is that the user uses one or more subject-specific filter lists
 * sourced online, such as those from [EasyList](https://easylist.to/). Custom
 * filter entries can then be used to add a small number of additional filters
 * to customise the generic filter lists.
 *
 * Each filter list is a mapping from an ID to a URI which contains the list.
 * The ID is needed so user interfaces can consistently refer to the same list
 * in the UI even if its URI changes over time. IDs must be non-empty UTF-8
 * strings.
 *
 * The filter list downloaded from the URI must be a list of hostnames,
 * separated by newlines (`\n`). Comments start with `#` and continue to the
 * next newline (`\n`). Each entry in the list must be a plain hostname — globs,
 * wildcards and regexps are not supported. Hostnames do not have to have a
 * trailing dot (`.`) as in DNS records.
 *
 * This is essentially the same format as `/etc/hosts`, as malcontent is
 * designed to consume general purpose filter lists produced for use in
 * `/etc/hosts`.
 *
 * Custom filter entries must follow the same format: they must be a plain
 * hostname — globs, wildcards and regexps are not supported.
 *
 * Since: 0.14.0
 */
typedef struct _MctWebFilter MctWebFilter;
GType mct_web_filter_get_type (void);
#define MCT_TYPE_WEB_FILTER mct_web_filter_get_type ()

MctWebFilter *mct_web_filter_ref (MctWebFilter *filter);
void mct_web_filter_unref (MctWebFilter *filter);

G_DEFINE_AUTOPTR_CLEANUP_FUNC (MctWebFilter, mct_web_filter_unref)

uid_t mct_web_filter_get_user_id (MctWebFilter *filter);

gboolean mct_web_filter_is_enabled (MctWebFilter *filter);

MctWebFilterType mct_web_filter_get_filter_type (MctWebFilter *filter);

GHashTable *mct_web_filter_get_block_lists (MctWebFilter *filter);
const char * const *mct_web_filter_get_custom_block_list (MctWebFilter *filter,
                                                          size_t       *out_len);

GHashTable *mct_web_filter_get_allow_lists (MctWebFilter *filter);
const char * const *mct_web_filter_get_custom_allow_list (MctWebFilter *filter,
                                                          size_t       *out_len);

gboolean mct_web_filter_get_force_safe_search (MctWebFilter *filter);

GVariant *mct_web_filter_serialize (MctWebFilter  *filter);
MctWebFilter *mct_web_filter_deserialize (GVariant  *variant,
                                          uid_t      user_id,
                                          GError   **error);

gboolean mct_web_filter_equal (MctWebFilter *a,
                               MctWebFilter *b);

gboolean mct_web_filter_validate_filter_id (const char *id);
gboolean mct_web_filter_validate_hostname (const char *hostname);
gboolean mct_web_filter_validate_hostname_len (const char *hostname,
                                               size_t      max_len);
gboolean mct_web_filter_validate_domain_name (const char *domain_name);
gboolean mct_web_filter_validate_domain_name_len (const char *domain_name,
                                                  size_t      max_len);

/**
 * MctWebFilterBuilder:
 *
 * [struct@Malcontent.WebFilterBuilder] is a stack-allocated mutable structure
 * used to build a [struct@Malcontent.WebFilter] instance.
 *
 * Use [method@Malcontent.WebFilterBuilder.init], various method calls to set
 * properties of the web filter, and then
 * [method@Malcontent.WebFilterBuilder.end], to construct a
 * [struct@Malcontent.WebFilter].
 *
 * Since: 0.14.0
 */
typedef struct
{
  /*< private >*/
  int i0;
  void *p0;
  void *p1;
  void *p2;
  void *p3;
  gboolean b0;
  gpointer p4[10];
} MctWebFilterBuilder;

GType mct_web_filter_builder_get_type (void);

/**
 * MCT_WEB_FILTER_BUILDER_INIT:
 *
 * Initialise a stack-allocated [struct@Malcontent.WebFilterBuilder] instance at
 * declaration time.
 *
 * This is typically used with `g_auto()`:
 * ```c
 * g_auto(MctWebFilterBuilder) builder = MCT_WEB_FILTER_BUILDER_INIT ();
 * ```
 *
 * Since: 0.14.0
 */
#define MCT_WEB_FILTER_BUILDER_INIT() \
  { \
    0,  /* MCT_WEB_FILTER_TYPE_NONE */ \
    NULL, \
    NULL, \
    NULL, \
    NULL, \
    FALSE, \
    /* padding: */ \
    { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } \
  }

void mct_web_filter_builder_init (MctWebFilterBuilder *builder);
void mct_web_filter_builder_clear (MctWebFilterBuilder *builder);

G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (MctWebFilterBuilder,
                                  mct_web_filter_builder_clear)

MctWebFilterBuilder *mct_web_filter_builder_new  (void);
MctWebFilterBuilder *mct_web_filter_builder_copy (MctWebFilterBuilder *builder);
void mct_web_filter_builder_free (MctWebFilterBuilder *builder);

G_DEFINE_AUTOPTR_CLEANUP_FUNC (MctWebFilterBuilder, mct_web_filter_builder_free)

MctWebFilter *mct_web_filter_builder_end (MctWebFilterBuilder *builder);

void mct_web_filter_builder_set_filter_type (MctWebFilterBuilder *builder,
                                             MctWebFilterType     filter_type);

void mct_web_filter_builder_add_block_list (MctWebFilterBuilder *builder,
                                            const char          *id,
                                            const char          *filter_uri);
void mct_web_filter_builder_add_custom_block_list_entry (MctWebFilterBuilder *builder,
                                                         const char          *hostname);

void mct_web_filter_builder_add_allow_list (MctWebFilterBuilder *builder,
                                            const char          *id,
                                            const char          *filter_uri);
void mct_web_filter_builder_add_custom_allow_list_entry (MctWebFilterBuilder *builder,
                                                         const char          *hostname);

void mct_web_filter_builder_set_force_safe_search (MctWebFilterBuilder *builder,
                                                   gboolean             force_safe_search);

G_END_DECLS
