<?php

/**
 * TextRenderer - Wrapper for RFont text rendering
 */

namespace PHPNative\Framework;

class TextRenderer
{
    private $renderer;
    private $font = null;
    private bool $initialized = false;
    private string $fontPath;
    private int $fontSize;
    private float $colorR = 1.0;
    private float $colorG = 1.0;
    private float $colorB = 1.0;
    private float $colorA = 1.0;

    /**
     * Constructor
     *
     * @param resource $renderer SDL Renderer resource
     */
    public function __construct($renderer)
    {
        $this->renderer = $renderer;
    }

    /**
     * Initialize TTF with a font file
     *
     * @param string|null $fontPath Path to TTF font file
     * @param int $fontSize Default font size
     * @param int $atlasWidth Font atlas texture width (ignored, for compatibility)
     * @param int $atlasHeight Font atlas texture height (ignored, for compatibility)
     * @return bool Success
     */
    public function init(
        null|string $fontPath = null,
        int $fontSize = 16,
        int $atlasWidth = 512,
        int $atlasHeight = 512,
    ): bool {
        // Try to find a suitable font if none provided
        if ($fontPath === null) {
            $fontPath = $this->findSystemFont();
        }

        if (!file_exists($fontPath)) {
            error_log("Font file not found: {$fontPath}");
            return false;
        }

        $this->fontPath = $fontPath;
        $this->fontSize = $fontSize;

        $this->font = ttf_open_font($fontPath, $fontSize);

        if (!$this->font) {
            error_log("Failed to open font: {$fontPath}");
            $this->initialized = false;
            return false;
        }

        $this->initialized = true;

        // Set default color to white
        $this->setColor(1.0, 1.0, 1.0, 1.0);

        return true;
    }

    /**
     * Find a system font
     *
     * @return string|null Font path or null if not found
     */
    private function findSystemFont(): null|string
    {
        $fontPaths = [
            // Linux
            '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf',
            '/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf',
            '/usr/share/fonts/TTF/DejaVuSans.ttf',
            // macOS
            '/System/Library/Fonts/Helvetica.ttc',
            '/Library/Fonts/Arial.ttf',
            // Windows
            'C:/Windows/Fonts/arial.ttf',
            'C:/Windows/Fonts/calibri.ttf',
        ];

        foreach ($fontPaths as $path) {
            if (file_exists($path)) {
                return $path;
            }
        }

        return null;
    }

    /**
     * Draw text at position
     *
     * @param string $text Text to draw
     * @param int $x X position
     * @param int $y Y position
     * @param int|null $size Font size
     */
    public function drawText(string $text, int $x, int $y, null|int $size = null): void
    {
        if (!$this->initialized || !$this->font) {
            return;
        }

        // SDL_ttf doesn't support variable font sizes easily
        // We use the font size that was set when the font was opened
        // For different sizes, you'd need to open multiple font instances

        // Convert float color (0.0-1.0) to int (0-255)
        $r = (int) ($this->colorR * 255);
        $g = (int) ($this->colorG * 255);
        $b = (int) ($this->colorB * 255);

        // Render text to surface with anti-aliasing (blended mode for smooth text)
        if (strlen($text) < 1) {
            return;
        }
        $surface = ttf_render_text_blended($this->font, $text, $r, $g, $b);
        if (!$surface) {
            return;
        }

        // Create texture from surface
        $texture = sdl_create_texture_from_surface($this->renderer, $surface);
        if (!$texture) {
            return;
        }

        // Get text size
        $textSize = ttf_size_text($this->font, $text);

        // Render texture
        sdl_render_texture($this->renderer, $texture, [
            'x' => $x,
            'y' => $y,
            'w' => $textSize['w'],
            'h' => $textSize['h'],
        ]);
        // Note: Texture and surface are automatically cleaned up by PHP resource destructors
    }

    /**
     * Create an SDL texture for the given text using the current color settings.
     *
     * @param string $text Text to render into a texture
     * @return array|null Returns ['texture' => resource, 'width' => int, 'height' => int] or null on failure
     */
    public function createTextTexture(string $text): null|array
    {
        if (!$this->initialized || !$this->font) {
            return null;
        }

        $r = (int) ($this->colorR * 255);
        $g = (int) ($this->colorG * 255);
        $b = (int) ($this->colorB * 255);
        if (strlen($text) < 1) {
            return null;
        }
        $surface = ttf_render_text_blended($this->font, $text, $r, $g, $b);
        if (!$surface) {
            return null;
        }

        $texture = sdl_create_texture_from_surface($this->renderer, $surface);
        if (!$texture) {
            return null;
        }

        $dimensions = ttf_size_text($this->font, $text);

        sdl_set_texture_blend_mode($texture, SDL_BLENDMODE_BLEND);
        if (\function_exists('sdl_set_texture_alpha_mod')) {
            sdl_set_texture_alpha_mod($texture, (int) ($this->colorA * 255));
        }

        return [
            'texture' => $texture,
            'width' => (int) $dimensions['w'],
            'height' => (int) $dimensions['h'],
        ];
    }

    /**
     * Set text color
     *
     * @param float $r Red (0.0 - 1.0)
     * @param float $g Green (0.0 - 1.0)
     * @param float $b Blue (0.0 - 1.0)
     * @param float $a Alpha (0.0 - 1.0)
     */
    public function setColor(float $r, float $g, float $b, float $a = 1.0): void
    {
        $this->colorR = $r;
        $this->colorG = $g;
        $this->colorB = $b;
        $this->colorA = $a;
    }

    /**
     * Measure text dimensions
     *
     * @param string $text Text to measure
     * @param int|null $size Font size
     * @return array [width, height]
     */
    public function measureText(string $text, null|int $size = null): array
    {
        if (!$this->initialized || !$this->font) {
            return [0, 0];
        }

        // Get text size using TTF
        $dimensions = ttf_size_text($this->font, $text);
        return [(int) $dimensions['w'], (int) $dimensions['h']];
    }

    /**
     * Update framebuffer size (call on window resize)
     *
     * @param int $width Window width
     * @param int $height Window height
     */
    public function updateFramebuffer(int $width, int $height): void
    {
        // SDL3 handles this automatically through the renderer
        // This method is kept for compatibility but does nothing
    }

    /**
     * Free TTF resources
     */
    public function free(): void
    {
        if ($this->initialized && $this->font) {
            ttf_close_font($this->font);
            $this->font = null;
            $this->initialized = false;
        }
    }

    /**
     * Check if initialized
     *
     * @return bool
     */
    public function isInitialized(): bool
    {
        return $this->initialized;
    }

    /**
     * Destructor
     */
    public function __destruct()
    {
        $this->free();
    }
}
