// DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers
// Released under the GPLv3

#pragma once

#include "imgui.h"

#include <vector>

namespace dragonx {
namespace util {

/**
 * @brief Downscaled RGBA frame sequence for an image (1 frame for stills, N for animations).
 */
struct AnimFrames {
    std::vector<std::vector<unsigned char>> frames;  ///< each is w*h*4 RGBA (already downscaled)
    std::vector<float> delaysSec;                    ///< per-frame duration in seconds (parallel to frames)
    int w = 0;
    int h = 0;
};

/**
 * @brief Decode an image into 1+ downscaled RGBA frames plus per-frame durations.
 *
 * Animated GIF (via stb) and animated WebP (via libwebp WebPAnimDecoder) return every frame (capped at
 * maxFrames); static formats — and APNG, which stb reads as a single image — return one frame. Frames
 * are box-downscaled internally (smaller for animations to bound VRAM). The caller uploads each frame
 * with CreateRawTexture. Returns false on decode failure.
 */
bool LoadAnimatedRGBA(const char* path, int maxFrames, AnimFrames& out);

/**
 * @brief Cheaply report whether an image file is an animation (multi-frame GIF or animated WebP),
 *        WITHOUT a full decode — a header/structure probe. False for stills + non-animatable formats.
 */
bool IsAnimatedImageFile(const char* path);

/**
 * @brief Load a PNG/JPG/BMP image from disk into an OpenGL or DX11 texture.
 * @param path  File path (relative to working directory or absolute)
 * @param outTexID  Receives the ImTextureID for ImGui rendering
 * @param outW  Receives image width
 * @param outH  Receives image height
 * @return true on success
 *
 * The caller is responsible for destroying the texture.
 * On OpenGL, cast outTexID to GLuint and call glDeleteTextures.
 */
bool LoadTextureFromFile(const char* path, ImTextureID* outTexID, int* outW, int* outH);

/**
 * @brief Load a PNG/JPG/BMP image from memory into an OpenGL or DX11 texture.
 * @param data       Pointer to compressed image data (e.g. PNG bytes)
 * @param dataSize   Size of the data in bytes
 * @param outTexID   Receives the ImTextureID for ImGui rendering
 * @param outW       Receives image width
 * @param outH       Receives image height
 * @return true on success
 */
bool LoadTextureFromMemory(const unsigned char* data, size_t dataSize,
                           ImTextureID* outTexID, int* outW, int* outH);

/**
 * @brief Create a texture from raw RGBA pixel data (no decoding needed).
 * @param pixels     Pointer to RGBA pixel data (4 bytes per pixel, caller-owned)
 * @param w          Image width
 * @param h          Image height
 * @param repeat     If true, set wrap mode to GL_REPEAT (for tiling); else CLAMP_TO_EDGE
 * @param outTexID   Receives the ImTextureID
 * @return true on success
 */
bool CreateRawTexture(const unsigned char* pixels, int w, int h,
                      bool repeat, ImTextureID* outTexID);

/**
 * @brief Load raw RGBA pixel data from a PNG/JPG/BMP file (no GPU texture).
 * @param path     File path
 * @param outW     Receives image width
 * @param outH     Receives image height
 * @return Pointer to RGBA pixels (caller must free with FreeRawPixels), or nullptr on failure
 */
unsigned char* LoadRawPixelsFromFile(const char* path, int* outW, int* outH);

/**
 * @brief Load raw RGBA pixel data from in-memory compressed image data (no GPU texture).
 * @param data     Pointer to compressed image data (e.g. PNG bytes)
 * @param dataSize Size of the data in bytes
 * @param outW     Receives image width
 * @param outH     Receives image height
 * @return Pointer to RGBA pixels (caller must free with FreeRawPixels), or nullptr on failure
 */
unsigned char* LoadRawPixelsFromMemory(const unsigned char* data, size_t dataSize, int* outW, int* outH);

/**
 * @brief Free pixels returned by LoadRawPixelsFromFile / LoadRawPixelsFromMemory.
 */
void FreeRawPixels(unsigned char* pixels);

/**
 * @brief Destroy a GPU texture previously created by Load/CreateRaw functions.
 * @param texID Texture handle (GLuint on OpenGL, ID3D11ShaderResourceView* on DX11)
 */
void DestroyTexture(ImTextureID texID);

} // namespace util
} // namespace dragonx
