<?php

namespace PHPNative\Ui;

/**
 * RenderStack manages layered rendering based on z-index
 * Optimizes rendering by only re-rendering dirty layers
 */
class RenderStack
{
    private array $layers = [];
    private int $nextLayerId = 0;

    public function __construct(
        public $renderer,
        public $textRenderer,
    ) {}

    /**
     * Add a render layer to the stack
     *
     * @param int $zIndex Lower values render first (behind), higher values render last (in front)
     * @param callable $renderCallback Function that performs the rendering
     * @param array $bounds ['x' => float, 'y' => float, 'w' => float, 'h' => float]
     * @return int Layer ID
     */
    public function addLayer(int $zIndex, callable $renderCallback, array $bounds): int
    {
        $layerId = $this->nextLayerId++;

        $this->layers[$layerId] = [
            'id' => $layerId,
            'zIndex' => $zIndex,
            'callback' => $renderCallback,
            'bounds' => $bounds,
        ];

        return $layerId;
    }

    /**
     * Remove a layer from the stack
     */
    public function removeLayer(int $layerId): void
    {
        unset($this->layers[$layerId]);
    }

    /**
     * Clear all layers
     */
    public function clear(): void
    {
        $this->layers = [];
    }

    /**
     * Render all layers sorted by z-index
     */
    public function renderAll(): void
    {
        // Sort layers by z-index (lower first)
        $sortedLayers = $this->layers;
        usort($sortedLayers, function ($a, $b) {
            return $a['zIndex'] <=> $b['zIndex'];
        });

        // Render each layer
        foreach ($sortedLayers as $layer) {
            ($layer['callback'])($this->renderer, $this->textRenderer);
        }
    }

    public function beginRender(): void
    {
        $this->savedViewport = $component->getViewport();

        // Create texture for this component
        $texture = sdl_create_texture(
            $renderer,
            SDL_PIXELFORMAT_RGBA8888,
            SDL_TEXTUREACCESS_TARGET,
            $viewport->width,
            $viewport->height,
        );

        // Enable alpha blending for the texture
        sdl_set_texture_blend_mode($texture, SDL_BLENDMODE_BLEND);

        // Save current render target
        $previousTarget = sdl_get_render_target($renderer);

        // Set texture as render target
        sdl_set_render_target($renderer, $texture);

        // Clear texture with transparent background
        sdl_set_render_draw_color($renderer, 0, 0, 0, 0);
        sdl_render_clear($renderer);

        // Temporarily adjust viewport for texture-relative rendering
        $viewport = clone $this->savedViewport;
        $originalX = $viewport->x;
        $originalY = $viewport->y;
        $viewport->x = 0;
        $viewport->y = 0;
    }

    public function endRender(): void
    {
    }

    public function render($renderer, $textRenderer, bool $onlyDirty = true): void
    {
    }

    /**
     * Render a single component with texture caching
     */
    private function renderComponentWithCache($renderer, $textRenderer, Component $component): void
    {
        $viewport = $component->getViewport();

        // Skip if component has no size
        if ($viewport->width <= 0 || $viewport->height <= 0) {
            return;
        }
        // Check if we should use texture caching
        if ($component->useTextureCache() && !$component->isDirty() && $component->getCachedTexture() !== null) {
            // Use cached texture - just copy it to the screen
            $cachedTexture = $component->getCachedTexture();

            sdl_render_texture($renderer, $cachedTexture, [
                'x' => $viewport->x,
                'y' => $viewport->y,
                'w' => $viewport->width,
                'h' => $viewport->height,
            ]);
        } elseif ($component->useTextureCache() && $component->isDirty()) {
            // Component is dirty - render to texture and cache it
            $this->renderToTextureAndCache($renderer, $textRenderer, $component);
        } else {
            // Texture caching disabled - render directly
            $component->render($renderer, $textRenderer);
            $component->renderContent($renderer, $textRenderer);
        }

        // Mark as clean after rendering
        $component->markClean();
    }

    /**
     * Render component to a texture and cache it
     */
    private function renderToTextureAndCache($renderer, $textRenderer, Component $component): void
    {
        $viewport = $component->getViewport();

        // Create texture for this component
        $texture = sdl_create_texture(
            $renderer,
            SDL_PIXELFORMAT_RGBA8888,
            SDL_TEXTUREACCESS_TARGET,
            $viewport->width,
            $viewport->height,
        );

        if (!$texture) {
            // Fallback: render directly if texture creation failed
            $component->render($renderer, $textRenderer);
            $component->renderContent($renderer, $textRenderer);
            return;
        }

        // Enable alpha blending for the texture
        sdl_set_texture_blend_mode($texture, SDL_BLENDMODE_BLEND);

        // Save current render target
        $previousTarget = sdl_get_render_target($renderer);

        // Set texture as render target
        sdl_set_render_target($renderer, $texture);

        // Clear texture with transparent background
        sdl_set_render_draw_color($renderer, 0, 0, 0, 0);
        sdl_render_clear($renderer);

        // Temporarily adjust viewport for texture-relative rendering
        $originalX = $viewport->x;
        $originalY = $viewport->y;
        $viewport->x = 0;
        $viewport->y = 0;

        // Render component into texture
        $component->render($renderer, $textRenderer);
        $component->renderContent($renderer, $textRenderer);

        // Restore original viewport position
        $viewport->x = $originalX;
        $viewport->y = $originalY;

        // Restore previous render target
        sdl_set_render_target($renderer, $previousTarget);

        // Cache the texture
        $component->setCachedTexture($texture);

        // Now render the cached texture to screen
        sdl_render_texture($renderer, $texture, [
            'x' => $viewport->x,
            'y' => $viewport->y,
            'w' => $viewport->width,
            'h' => $viewport->height,
        ]);
    }
}
