/* ========================================================================= */
/**
 * @file libwlclient.h
 *
 * @copyright
 * Copyright 2023 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef __LIBWLCLIENT_H__
#define __LIBWLCLIENT_H__

#include <inttypes.h>
#include <stdbool.h>
#include <libbase/libbase.h>
#include <wayland-server-core.h>
#include <xkbcommon/xkbcommon.h>

/** Forward declaration: Wayland client handle. */
typedef struct _wlclient_t wlclient_t;
struct zxdg_toplevel_decoration_v1;

#include "icon.h"
#include "xdg_toplevel.h"

#ifdef __cplusplus
extern "C" {
#endif  // __cplusplus

/**
 * A client's callback, as used in @ref wlclient_register_timer.
 *
 * @param wlclient_ptr
 * @param ud_ptr
 */
typedef void (*wlclient_callback_t)(
    wlclient_t *wlclient_ptr,
    void *ud_ptr);

/** Accessor to 'public' client attributes. */
typedef struct {
    /** Wayland display connection. */
    struct wl_display         *wl_display_ptr;
    /** The bound compositor interface. */
    struct wl_compositor      *wl_compositor_ptr;
    /** The bound SHM interface. */
    struct wl_shm             *wl_shm_ptr;
    /** The bound XDG wm_base interface. */
    struct xdg_wm_base        *xdg_wm_base_ptr;
    /** The bound seat. */
    struct wl_seat            *wl_seat_ptr;
    /** Pointer state, if & when the seat has the capability. */
    struct wl_pointer         *wl_pointer_ptr;
    /** The bound Toplevel Icon Manager. Will be NULL if not supported. */
    struct zwlmaker_icon_manager_v1 *icon_manager_ptr;
    /** The bound XDG decoration manager. NULL if not supported. */
    struct zxdg_decoration_manager_v1 *xdg_decoration_manager_ptr;
    /** The bound Input Observation. */
    struct ext_input_observation_manager_v1 *input_observation_manager_ptr;

    /** Application ID, as a string. Or NULL, if not set. */
    const char                *app_id_ptr;
} wlclient_attributes_t;

/** Events of the client. */
typedef struct {
    /** A key was pressed. */
    struct wl_signal          key;
} wlclient_events_t;

/** Key event. */
typedef struct{
    /** The key. */
    xkb_keysym_t              keysym;
    /** Wheter it was pressed (true) or released. */
    bool                      pressed;
} wlclient_key_event_t;

/**
 * Creates a wayland client for simple buffer interactions.
 *
 * @param app_id_ptr          Application ID or NULL if not set.
 *
 * @return The client state, or NULL on error. The state needs to be free'd
 *     via @ref wlclient_destroy.
 */
wlclient_t *wlclient_create(const char *app_id_ptr);

/**
 * Destroys the wayland client, as created by @ref wlclient_create.
 *
 * @param wlclient_ptr
 */
void wlclient_destroy(wlclient_t *wlclient_ptr);

/**
 * Gets the client attributes.
 *
 * @param wlclient_ptr
 *
 * @return A pointer to the attributes.
 */
const wlclient_attributes_t *wlclient_attributes(
    const wlclient_t *wlclient_ptr);

/** @return A pointer to @ref wlclient_t::events. */
wlclient_events_t *wlclient_events(wlclient_t *wlclient_ptr);

/**
 * Runs the client's mainloop.
 *
 * @param wlclient_ptr
 */
void wlclient_run(wlclient_t *wlclient_ptr);

/**
 * Requests termination of the client-s mainloop. This takes effect only once
 * the mainloop wraps up an iteration.
 *
 * @param wlclient_ptr
 */
void wlclient_request_terminate(wlclient_t *wlclient_ptr);

/**
 * Registers a timer with the client.
 *
 * Once the system clock reaches (or has passed) `target_usec`, `callback` will
 * be called with the provided arguments. This is a one-time registration. For
 * repeated calls, clients need to re-register.
 *
 * @param wlclient_ptr
 * @param target_usec
 * @param callback
 * @param callback_ud_ptr
 *
 * @return true on success.
 */
bool wlclient_register_timer(
    wlclient_t *wlclient_ptr,
    uint64_t target_usec,
    wlclient_callback_t callback,
    void *callback_ud_ptr);

#ifdef __cplusplus
}  // extern "C"
#endif  // __cplusplus

#endif /* __LIBWLCLIENT_H__ */
/* == End of libwlclient.h ================================================= */
