/*
 * Purple - Internet Messaging Library
 * Copyright (C) Pidgin Developers <devel@pidgin.im>
 *
 * Purple is the legal property of its developers, whose names are too numerous
 * to list here. Please refer to the COPYRIGHT file distributed with this
 * source distribution.
 *
 * This library 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; either version 2 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 General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this library; if not, see <https://www.gnu.org/licenses/>.
 */

#if !defined(PURPLE_GLOBAL_HEADER_INSIDE) && !defined(PURPLE_COMPILATION)
# error "only <purple.h> may be included directly"
#endif

#ifndef PURPLE_UI_H
#define PURPLE_UI_H

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

#include "purpleaccountmanagerbackend.h"
#include "purplecontactmanagerbackend.h"
#include "purpleconversationmanagerbackend.h"
#include "purplepresencemanagerbackend.h"
#include "purpleschedulerbackend.h"
#include "purpleversion.h"

G_BEGIN_DECLS

#define PURPLE_UI_ERROR purple_ui_error_quark()

/**
 * PurpleUiError:
 * @PURPLE_UI_ERROR_VFUNC_NOT_IMPLEMENTED: The requested virtual function is
 *  not implemented.
 *
 * Error codes returned by the user interface abstraction.
 *
 * Since: 3.0
 */
typedef enum {
    PURPLE_UI_ERROR_VFUNC_NOT_IMPLEMENTED PURPLE_AVAILABLE_ENUMERATOR_IN_3_0,
} PurpleUiError;

/**
 * purple_ui_error_quark:
 *
 * The error domain to identify errors with the user interface abstraction.
 *
 * Returns: The error domain.
 *
 * Since: 0.3
 */
PURPLE_AVAILABLE_IN_3_0
GQuark purple_ui_error_quark(void);

#define PURPLE_TYPE_UI (purple_ui_get_type())

PURPLE_AVAILABLE_IN_3_0
G_DECLARE_DERIVABLE_TYPE(PurpleUi, purple_ui, PURPLE, UI, GObject)

/**
 * PurpleUi:
 *
 * An abstract class representing a user interface.
 *
 * All user interfaces must create a subclass of this and pass it to
 * [ctor@Core.new].
 *
 * Since: 3.0
 */

struct _PurpleUiClass {
	GObjectClass parent;

	PurpleAccountManagerBackend *(*get_account_manager_backend)(PurpleUi *ui, GError **error);

	PurpleContactManagerBackend *(*get_contact_manager_backend)(PurpleUi *ui, GError **error);

	PurpleConversationManagerBackend *(*get_conversation_manager_backend)(PurpleUi *ui, GError **error);

	char *(*get_display_version)(PurpleUi *ui);

	PurplePresenceManagerBackend *(*get_presence_manager_backend)(PurpleUi *ui, GError **error);

	PurpleSchedulerBackend *(*get_scheduler_backend)(PurpleUi *ui, GError **error);

	gpointer (*get_settings_backend)(PurpleUi *ui);

	char *(*get_user_agent)(PurpleUi *ui);

	void (*open_uri)(PurpleUi *ui, const char *uri, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data);

	gboolean (*open_uri_finish)(PurpleUi *ui, GAsyncResult *result, GError **error);

	gboolean (*start)(PurpleUi *ui, GError **error);
	void (*stop)(PurpleUi *ui);

	gpointer reserved[8];
};

/**
 * purple_ui_get_account_manager_backend:
 * @error: (out) (nullable): a return address for a #GError
 *
 * Gets the [class@AccountManagerBackend] that the user interface wants to use.
 *
 * > Note: This should typically only be called by libpurple. If this returns
 * %NULL, then libpurple will not be able to persist accounts.
 *
 * Returns: (transfer full) (nullable): The new account manager backend.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
PurpleAccountManagerBackend *purple_ui_get_account_manager_backend(PurpleUi *ui, GError **error);

/**
 * purple_ui_get_client_type:
 *
 * Gets the client type.
 *
 * Returns: (transfer none): The client type.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
const char *purple_ui_get_client_type(PurpleUi *ui);

/**
 * purple_ui_get_contact_manager_backend:
 * @error: (out) (nullable): a return address for a #GError
 *
 * Gets the [class@ContactManagerBackend] that the user interface wants to use.
 *
 * > Note: This should typically only be called by libpurple. If this returns
 * %NULL, then libpurple will not be able to persist contacts.
 *
 * Returns: (transfer full) (nullable): The new contact manager backend.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
PurpleContactManagerBackend *purple_ui_get_contact_manager_backend(PurpleUi *ui, GError **error);

/**
 * purple_ui_get_conversation_manager_backend:
 * @error: (out) (nullable): a return address for a #GError
 *
 * Gets the [class@ConversationManagerBackend] that the user interface wants to
 * use.
 *
 * > Note: This should typically only be called by libpurple. If this returns
 * %NULL, then libpurple will not be able to persist conversations.
 *
 * Returns: (transfer full) (nullable): The new backend.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
PurpleConversationManagerBackend *purple_ui_get_conversation_manager_backend(PurpleUi *ui, GError **error);

/**
 * purple_ui_get_display_version:
 *
 * Gets a display version string for the user interface.
 *
 * This is intended to be used as a response to queries about the client's name
 * and version.
 *
 * User interfaces may override this.
 *
 * Returns: (transfer full) (nullable): The display version string.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
char *purple_ui_get_display_version(PurpleUi *ui);

/**
 * purple_ui_get_id:
 *
 * Gets the id.
 *
 * Returns: The id.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
const char *purple_ui_get_id(PurpleUi *ui);

/**
 * purple_ui_get_name:
 *
 * Gets the name.
 *
 * This should be translated.
 *
 * Returns: The name.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
const char *purple_ui_get_name(PurpleUi *ui);

/**
 * purple_ui_open_uri:
 * @uri: the URI to open
 * @cancellable: (nullable): an optional #GCancellable
 * @callback: (nullable) (scope async): a callback to call with the results
 * @data: the user data to pass to the callback
 *
 * Attempts to open a URI.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
void purple_ui_open_uri(PurpleUi *ui, const char *uri, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data);

/**
 * purple_ui_open_uri_finish:
 * @result: the result
 * @error: (out) (nullable): a return address for a #GError
 *
 * Finishes a previous call to [method@Ui.open_uri].
 *
 * Returns: true if the URI was opened successfully.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
gboolean purple_ui_open_uri_finish(PurpleUi *ui, GAsyncResult *result, GError **error);

/**
 * purple_ui_get_presence_manager_backend:
 * @error: (out) (nullable): a return address for a #GError
 *
 * Gets the [class@PresenceManagerBackend] that the user interface wants to
 * use.
 *
 * > Note: This should typically only be called by libpurple. If this returns
 * %NULL, then libpurple will not be able to persist saved presences.
 *
 * Returns: (transfer full) (nullable): The new backend.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
PurplePresenceManagerBackend *purple_ui_get_presence_manager_backend(PurpleUi *ui, GError **error);

/**
 * purple_ui_get_scheduler_backend:
 * @error: (out) (nullable): a return address for a #GError
 *
 * Gets the [class@SchedulerBackend] that the user interface wants to use.
 *
 * > Note: This should typically only be called by libpurple. If this returns
 * %NULL, then libpurple will not be able to persist scheduled tasks.
 *
 * Returns: (transfer full) (nullable): The new scheduler backend.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
PurpleSchedulerBackend *purple_ui_get_scheduler_backend(PurpleUi *ui, GError **error);

/**
 * purple_ui_get_settings_backend:
 *
 * Get the [class@Gio.SettingsBackend] that the user interface is using for
 * its settings.
 *
 * > Note: This should only be called by libpurple.
 *
 * Returns: (transfer full): The settings that @ui is using.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
gpointer purple_ui_get_settings_backend(PurpleUi *ui);

/**
 * purple_ui_get_support_website:
 *
 * Gets the support website.
 *
 * Returns: (nullable): The support website.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
const char *purple_ui_get_support_website(PurpleUi *ui);

/**
 * purple_ui_get_user_agent:
 *
 * Gets a user agent string for the user interface.
 *
 * This is intended to be used as an HTTP header.
 *
 * User interfaces may override this.
 *
 * Returns: (transfer full) (nullable): The user agent string.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
char *purple_ui_get_user_agent(PurpleUi *ui);

/**
 * purple_ui_get_version:
 *
 * Gets the version.
 *
 * Returns: The version.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
const char *purple_ui_get_version(PurpleUi *ui);

/**
 * purple_ui_get_website:
 *
 * Gets the website.
 *
 * Returns: (nullable): The website.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
const char *purple_ui_get_website(PurpleUi *ui);

/**
 * purple_ui_start:
 * @error: (out) (nullable): a return address for a #GError
 *
 * Tells the user interface that libpurple is done initializing and that the
 * user interface should continue its initialization.
 *
 * The user interface can return errors here which will be propagated by
 * [method@Purple.Core.start] which calls this function.
 *
 * > Note: This should only be called by libpurple.
 *
 * Returns: true on success.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
gboolean purple_ui_start(PurpleUi *ui, GError **error);

/**
 * purple_ui_stop:
 *
 * Tells the user interface that libpurple is done shutting down.
 *
 * > Note: This should only be called by libpurple.
 *
 * Since: 3.0
 */
PURPLE_AVAILABLE_IN_3_0
void purple_ui_stop(PurpleUi *ui);

G_END_DECLS

#endif /* PURPLE_UI_H */
