/*
 * Copyright (c) 2024-2025, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <AK/AtomicRefCounted.h>
#include <AK/Function.h>
#include <AK/NonnullOwnPtr.h>
#include <AK/RefPtr.h>
#include <LibGfx/Color.h>
#include <LibGfx/Size.h>
#include <LibGfx/SkiaBackendContext.h>

#ifdef USE_VULKAN_DMABUF_IMAGES
namespace Gfx {

struct VulkanImage;

}
#endif

#ifdef AK_OS_MACOS
#    include <LibGfx/MetalContext.h>
#endif

class SkCanvas;
class SkSurface;

namespace Gfx {

class PaintingSurface : public AtomicRefCounted<PaintingSurface> {
public:
    enum class Origin {
        TopLeft,
        BottomLeft,
    };

    Function<void(PaintingSurface&)> on_flush;

    static NonnullRefPtr<PaintingSurface> create_with_size(IntSize size, BitmapFormat color_type, AlphaType alpha_type, RefPtr<SkiaBackendContext> = {});
    static NonnullRefPtr<PaintingSurface> wrap_bitmap(Bitmap&);

#ifdef AK_OS_MACOS
    static NonnullRefPtr<PaintingSurface> create_from_shared_image_buffer(SharedImageBuffer&, NonnullRefPtr<SkiaBackendContext>, Origin = Origin::TopLeft);
#endif

#ifdef USE_VULKAN_DMABUF_IMAGES
    static NonnullRefPtr<PaintingSurface> create_from_vkimage(NonnullRefPtr<SkiaBackendContext> context, NonnullRefPtr<VulkanImage> vulkan_image, Origin origin);
#endif

    NonnullRefPtr<Bitmap> snapshot_bitmap() const;

    void read_into_bitmap(Bitmap&) const;
    void write_from_bitmap(Bitmap const&);

    void notify_content_will_change();

    IntSize size() const;
    IntRect rect() const;

    SkCanvas& canvas() const;
    SkSurface& sk_surface() const;

    template<typename T>
    T sk_image_snapshot() const;

    RefPtr<SkiaBackendContext> skia_backend_context() const;

    void flush();

    ~PaintingSurface();

private:
    struct Impl;

    PaintingSurface(NonnullOwnPtr<Impl>&&);

    NonnullOwnPtr<Impl> m_impl;
};

}
