#pragma once

#include "shape.hpp"
#include "defines.hpp"  // Para PNG_IDLE_TIME_MIN/MAX constantes
#include <vector>
#include <cstdlib>       // Para rand()

// Figura: Shape generada desde PNG 1-bit (blanco sobre negro)
// Enfoque A: Extrusión 2D (implementado)
// Enfoque B: Voxelización 3D (preparado para futuro)
class PNGShape : public Shape {
private:
    // Datos de la imagen cargada
    int image_width_ = 0;
    int image_height_ = 0;
    std::vector<bool> pixel_data_;  // Mapa de píxeles blancos (true = blanco)

    // Puntos generados (Enfoque A: Extrusión 2D)
    struct Point2D {
        float x, y;
    };
    std::vector<Point2D> edge_points_;      // Contorno (solo bordes) - ORIGINAL sin optimizar
    std::vector<Point2D> filled_points_;    // Relleno completo - ORIGINAL sin optimizar
    std::vector<Point2D> optimized_points_; // Puntos finales optimizados (usado por getPoint3D)

    // Parámetros de extrusión
    float extrusion_depth_ = 0.0f;          // Profundidad de extrusión en Z
    int num_layers_ = 0;                    // Capas de extrusión (más capas = más denso)

    // Rotación "legible" (de frente con volteretas ocasionales)
    float angle_x_ = 0.0f;
    float angle_y_ = 0.0f;
    float idle_timer_ = 0.0f;        // Timer para tiempo de frente
    float flip_timer_ = 0.0f;        // Timer para voltereta
    float next_idle_time_ = 5.0f;    // Próximo tiempo de espera (aleatorio)
    bool is_flipping_ = false;       // Estado: quieto o voltereta
    int flip_axis_ = 0;              // Eje de voltereta (0=X, 1=Y, 2=ambos)

    // Pivoteo sutil en estado IDLE
    float tilt_x_ = 0.0f;            // Oscilación sutil en eje X
    float tilt_y_ = 0.0f;            // Oscilación sutil en eje Y

    // Modo LOGO (intervalos de flip más largos)
    bool is_logo_mode_ = false;      // true = usar intervalos LOGO (más lentos)

    // Sistema de convergencia (solo relevante en modo LOGO)
    float current_convergence_ = 0.0f;           // Porcentaje actual de convergencia (0.0-1.0)
    bool convergence_threshold_reached_ = false; // true si ha alcanzado umbral mínimo (80%)

    // Sistema de tracking de flips (para modo LOGO - espera de flips)
    int flip_count_ = 0;             // Contador de flips completados (reset al entrar a LOGO)
    bool was_flipping_last_frame_ = false;  // Estado previo para detectar transiciones

    // Dimensiones normalizadas
    float scale_factor_ = 1.0f;
    float center_offset_x_ = 0.0f;
    float center_offset_y_ = 0.0f;

    int num_points_ = 0;  // Total de puntos generados (para indexación)

    // Métodos internos
    bool loadPNG(const char* path);         // Cargar PNG con stb_image
    void detectEdges();                     // Detectar contorno (Enfoque A)
    void floodFill();                       // Rellenar interior (Enfoque B - futuro)
    void generateExtrudedPoints();          // Generar puntos con extrusión 2D

    // Métodos de distribución adaptativa (funciones puras, no modifican parámetros)
    std::vector<Point2D> extractAlternateRows(const std::vector<Point2D>& source, int row_skip);  // Extraer filas alternas
    std::vector<Point2D> extractCornerVertices(const std::vector<Point2D>& source);                // Extraer vértices/esquinas

public:
    // Constructor: recibe path relativo al PNG
    PNGShape(const char* png_path = "data/shapes/jailgames.png");

    void generatePoints(int num_points, float screen_width, float screen_height) override;
    void update(float delta_time, float screen_width, float screen_height) override;
    void getPoint3D(int index, float& x, float& y, float& z) const override;
    const char* getName() const override { return "PNG SHAPE"; }
    float getScaleFactor(float screen_height) const override;

    // Consultar estado de flip
    bool isFlipping() const { return is_flipping_; }

    // Obtener progreso del flip actual (0.0 = inicio, 1.0 = fin)
    float getFlipProgress() const;

    // Obtener número de flips completados (para modo LOGO)
    int getFlipCount() const { return flip_count_; }

    // Resetear contador de flips (llamar al entrar a LOGO MODE)
    void resetFlipCount() { flip_count_ = 0; was_flipping_last_frame_ = false; }

    // Control de modo LOGO (flip intervals más largos)
    void setLogoMode(bool enable) {
        is_logo_mode_ = enable;
        // Recalcular next_idle_time_ con el rango apropiado
        float idle_min = enable ? PNG_IDLE_TIME_MIN_LOGO : PNG_IDLE_TIME_MIN;
        float idle_max = enable ? PNG_IDLE_TIME_MAX_LOGO : PNG_IDLE_TIME_MAX;
        next_idle_time_ = idle_min + (rand() % 1000) / 1000.0f * (idle_max - idle_min);
    }

    // Sistema de convergencia (override de Shape::setConvergence)
    void setConvergence(float convergence) override;
};
