#pragma once

#include <SDL3/SDL.h>

#include <string>  // Para string
#include <vector>  // Para vector

enum class PaletteColor : Uint8 {
    BLACK = 0,
    BRIGHT_BLACK = 1,

    BLUE = 2,
    BRIGHT_BLUE = 3,

    RED = 4,
    BRIGHT_RED = 5,

    MAGENTA = 6,
    BRIGHT_MAGENTA = 7,

    GREEN = 8,
    BRIGHT_GREEN = 9,

    CYAN = 10,
    BRIGHT_CYAN = 11,

    YELLOW = 12,
    BRIGHT_YELLOW = 13,

    WHITE = 14,
    BRIGHT_WHITE = 15,

    TRANSPARENT = 255,
};

// Estructura para definir un circulo
struct Circle {
        int x;
        int y;
        int r;
};

// Estructura para definir una linea horizontal
struct LineHorizontal {
        int x1, x2, y;
};

// Estructura para definir una linea vertical
struct LineVertical {
        int x, y1, y2;
};

// Estructura para definir una linea diagonal
struct LineDiagonal {
        int x1, y1, x2, y2;
};

// Estructura para definir una linea
struct Line {
        int x1, y1, x2, y2;
};

// Estructura para definir un color
struct Color {
        Uint8 r;
        Uint8 g;
        Uint8 b;

        // Constructor por defecto
        Color()
            : r(0),
              g(0),
              b(0) {}

        // Constructor
        Color(Uint8 red, Uint8 green, Uint8 blue)
            : r(red),
              g(green),
              b(blue) {}
};

// Calcula el cuadrado de la distancia entre dos puntos
auto distanceSquared(int x1, int y1, int x2, int y2) -> double;

// Detector de colisiones entre dos circulos
auto checkCollision(const Circle& a, const Circle& b) -> bool;

// Detector de colisiones entre un circulo y un rectangulo
auto checkCollision(const Circle& a, const SDL_FRect& rect) -> bool;

// Detector de colisiones entre un dos rectangulos
auto checkCollision(const SDL_FRect& a, const SDL_FRect& b) -> bool;

// Detector de colisiones entre un punto y un rectangulo
auto checkCollision(const SDL_FPoint& p, const SDL_FRect& r) -> bool;

// Detector de colisiones entre una linea horizontal y un rectangulo
auto checkCollision(const LineHorizontal& l, const SDL_FRect& r) -> bool;

// Detector de colisiones entre una linea vertical y un rectangulo
auto checkCollision(const LineVertical& l, const SDL_FRect& r) -> bool;

// Detector de colisiones entre una linea horizontal y un punto
auto checkCollision(const LineHorizontal& l, const SDL_FPoint& p) -> bool;

// Detector de colisiones entre dos lineas
auto checkCollision(const Line& l1, const Line& l2) -> SDL_Point;

// Detector de colisiones entre dos lineas
auto checkCollision(const LineDiagonal& l1, const LineVertical& l2) -> SDL_Point;

// Detector de colisiones entre un punto y una linea diagonal
auto checkCollision(const SDL_FPoint& p, const LineDiagonal& l) -> bool;

// Normaliza una linea diagonal
void normalizeLine(LineDiagonal& l);

// Devuelve un Color a partir de un string
auto stringToColor(const std::string& str) -> Uint8;

// Convierte una cadena a un entero de forma segura
auto safeStoi(const std::string& value, int default_value = 0) -> int;

// Convierte una cadena a un booleano
auto stringToBool(const std::string& str) -> bool;

// Convierte un booleano a una cadena
auto boolToString(bool value) -> std::string;

// Compara dos colores
auto colorAreEqual(Color color1, Color color2) -> bool;

// Convierte una cadena a minusculas
auto toLower(const std::string& str) -> std::string;

// Convierte una cadena a mayúsculas
auto toUpper(const std::string& str) -> std::string;

// Obtiene el nombre de un fichero a partir de una ruta
auto getFileName(const std::string& path) -> std::string;

// Obtiene la ruta eliminando el nombre del fichero
auto getPath(const std::string& full_path) -> std::string;

// Imprime por pantalla una linea de texto de tamaño fijo rellena con puntos
void printWithDots(const std::string& text1, const std::string& text2, const std::string& text3);

// Comprueba si una vector contiene una cadena
auto stringInVector(const std::vector<std::string>& vec, const std::string& str) -> bool;

// Hace sonar la música
void playMusic(const std::string& music_path);

// Rellena una textura de un color
void fillTextureWithColor(SDL_Renderer* renderer, SDL_Texture* texture, Uint8 r, Uint8 g, Uint8 b, Uint8 a);

inline auto toSDLRect(const SDL_FRect& frect) -> SDL_Rect {
    SDL_Rect rect;
    rect.x = static_cast<int>(frect.x);
    rect.y = static_cast<int>(frect.y);
    rect.w = static_cast<int>(frect.w);
    rect.h = static_cast<int>(frect.h);
    return rect;
}

inline auto toSDLPoint(const SDL_FPoint& fpoint) -> SDL_Point {
    SDL_Point point;
    point.x = static_cast<int>(fpoint.x);
    point.y = static_cast<int>(fpoint.y);
    return point;
}