/*
  Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>

  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely.
*/

/* Simple test of the SDL Notification API */
#define SDL_MAIN_USE_CALLBACKS 1
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <SDL3/SDL_test.h>

/* This enables themed Windows dialogs when building with Visual Studio */
#if defined(SDL_PLATFORM_WINDOWS) && defined(_MSC_VER)
#pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0'  processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif

static SDLTest_CommonState *state;
static SDL_Surface *icon;
static SDL_NotificationID last_id;
static SDL_PropertiesID props;
static SDL_NotificationAction actions[] = {
    { .button = { SDL_NOTIFICATION_ACTION_TYPE_BUTTON, "action_1", "OK" } },
    { .button = { SDL_NOTIFICATION_ACTION_TYPE_BUTTON, "action_2", "Cancel" } }
};

static bool transient;
static int sound;

SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
    SDL_SetAppMetadata("SDL Notification Test", "0.0.1", "org.libsdl.testnotification");

    /* Initialize test framework */
    state = SDLTest_CommonCreateState(argv, 0);
    if (!state) {
        return SDL_APP_FAILURE;
    }

    /* Parse commandline */
    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
        return SDL_APP_FAILURE;
    }

    state->flags |= SDL_INIT_VIDEO;
    if (!SDLTest_CommonInit(state)) {
        return SDL_APP_FAILURE;
    }

    SDL_SetStringProperty(SDL_GetGlobalProperties(), SDL_PROP_GLOBAL_NOTIFICATION_HEADER_ICON_STRING, "sdl-test_round.png");

    props = SDL_CreateProperties();
    SDL_SetStringProperty(props, SDL_PROP_NOTIFICATION_TITLE_STRING, "Test Notification");
    SDL_SetStringProperty(props, SDL_PROP_NOTIFICATION_MESSAGE_STRING, "Hey, pay attention to me!");

    icon = SDL_LoadPNG("sdl-test_round.png");
    SDL_SetPointerProperty(props, SDL_PROP_NOTIFICATION_IMAGE_POINTER, icon);

    SDL_SetPointerProperty(props, SDL_PROP_NOTIFICATION_ACTIONS_POINTER, actions);
    SDL_SetNumberProperty(props, SDL_PROP_NOTIFICATION_ACTION_COUNT_NUMBER, SDL_arraysize(actions));

    SDL_RequestNotificationPermission();

    return SDL_APP_CONTINUE;
}

static void ShowNotification(bool replace)
{
    if (replace) {
        SDL_SetNumberProperty(props, SDL_PROP_NOTIFICATION_REPLACES_NUMBER, last_id);
    } else {
        SDL_SetNumberProperty(props, SDL_PROP_NOTIFICATION_REPLACES_NUMBER, 0);
    }
    SDL_SetBooleanProperty(props, SDL_PROP_NOTIFICATION_TRANSIENT_BOOLEAN, transient);

    // Test showing a system notification message.
    const SDL_NotificationID new_id = SDL_ShowNotificationWithProperties(props);
    if (new_id) {
        SDL_Log("Notification successfully dispatched. ID: %" SDL_PRIu32, new_id);
        last_id = new_id;
    } else {
        SDL_Log("Notification dispatch failed: %s", SDL_GetError());
    }
}

SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
    if (event->type == SDL_EVENT_KEY_DOWN) {
        if (event->key.key == SDLK_SPACE) {
            ShowNotification((event->key.mod & SDL_KMOD_CTRL) != 0);
        } else if (event->key.key == SDLK_H) {
            if (last_id) {
                SDL_RemoveNotification(last_id);
            }
        } else if (event->key.key == SDLK_T) {
            transient ^= true;
        } else if (event->key.key == SDLK_S) {
            sound = (sound + 1) % 3;
            switch (sound) {
            default:
                SDL_SetStringProperty(props, SDL_PROP_NOTIFICATION_SOUND_STRING, "default");
                break;
            case 1:
                SDL_SetStringProperty(props, SDL_PROP_NOTIFICATION_SOUND_STRING, "sword.wav");
                break;
            case 2:
                SDL_SetStringProperty(props, SDL_PROP_NOTIFICATION_SOUND_STRING, "silent");
            }
        }
    } else if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
        ShowNotification(false);
    } else if (event->type == SDL_EVENT_NOTIFICATION_ACTION_INVOKED) {
        SDL_Log("User responded to notification %" SDL_PRIu32 " with action \"%s\"", event->notification.which, event->notification.action_id);

        // Raise the window of the user clicked "OK".
        if (SDL_strcmp(event->notification.action_id, "action_1") == 0) {
            SDL_RaiseWindow(state->windows[0]);
        } else if (SDL_strcmp(event->notification.action_id, "action_url") == 0) {
            SDL_OpenURL("https://www.libsdl.org");
        }
    }

    return SDLTest_CommonEventMainCallbacks(state, event);
}

SDL_AppResult SDL_AppIterate(void *appstate)
{
    for (int i = 0; i < state->num_windows; ++i) {
        SDL_Renderer *renderer = state->renderers[i];
        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
        SDL_RenderClear(renderer);
        SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);

        float y = 16.0f;
        SDL_RenderDebugText(renderer, 8.f, y, "Click or press space to show a notification");
        y += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE + 2;
        SDL_RenderDebugText(renderer, 8.f, y, "Press 'H' to hide the last notification");
        y += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE + 2;
        SDL_RenderDebugTextFormat(renderer, 8.f, y, "Press 'T' to toggle the transient property (%s)", transient ? "ON" : "OFF");
        y += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE + 2;
        SDL_RenderDebugTextFormat(renderer, 8.f, y, "Press 'S' to toggle the sound property (%s)", sound == 0 ? "Default" : sound == 1 ? "Custom"
                                                                                                                                       : "Silent");
        SDL_RenderPresent(renderer);
    }

    return SDL_APP_CONTINUE;
}

void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
    SDL_DestroySurface(icon);
    SDLTest_CommonQuit(state);
}
