#pragma once

#include <SDL2/SDL_rect.h>   // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include "utils.h"           // for Color
#include "moving_sprite.h"
#include "sprite.h"
#include "texture.h"
#include <memory>

/*
    Esta clase es la encargada de dibujar el fondo que aparece durante la sección
    jugable.

    Utiliza una textura donde compone la imagen y luego tiene una textura superior
    rellena de un color sólido cuya opacidad se puede modificar.

    El objeto tiene un tamaño total definido en la variable "rect". En principio este
    tamaño coincide con el tamaño de la ventana o resolución del juego, pero se pinta
    solo el rectangulo definido en srcRect en la posición de la pantalla definida en
    dstRect.

    Ambos rectangulos han de coincidir en tamaño y por definición, el punto comun es el inferior derecho el rectangulo.

    Utiliza varios métodos para definir su comportamiento:
        - setCloudsSpeed(float value)
          Velocidad a la que se desplazan las nubes cada frame

        - setGradientNumber(int value)
          Escoge el índice de la textura de fondo a usar (el color del cielo)

        - setTransition(float value)
          Porcentaje (entre 0.0f (textura actual) y 1.0f (textura siguiente)) para mostrar entre la textura de fondo actual y la siguiente

        - setSrcRect(SDL_Rect value)
          Rectangulo de la textura de fondo que se desea mostrar

        - setDstRecr(SDL_Rect value)
          Rectangulo de destino donde se mostrará el rectángulo antrior. Automaticamente modifica srcRect para coincidor en tamaño con el destino.

        - setColor(Color color)
          Establece el color de la textura de superposición

        - setAlpha(int alpha)
          Establece la transparencia de la textura de superposición
*/

// Clase Background
class Background
{
private:
  // Objetos y punteros
  SDL_Renderer *renderer_; // El renderizador de la ventana

  std::shared_ptr<Texture> buildings_texture_;     // Textura con los edificios de fondo
  std::shared_ptr<Texture> top_clouds_texture_;    // Textura con las nubes de fondo
  std::shared_ptr<Texture> bottom_clouds_texture_; // Textura con las nubes de fondo
  std::shared_ptr<Texture> grass_texture_;         // Textura con la hierba del suelo
  std::shared_ptr<Texture> gradients_texture_;     // Textura con los diferentes colores de fondo del juego

  std::unique_ptr<MovingSprite> top_clouds_sprite_a_;    // Sprite para las nubes superiores
  std::unique_ptr<MovingSprite> top_clouds_sprite_b_;    // Sprite para las nubes superiores
  std::unique_ptr<MovingSprite> bottom_clouds_sprite_a_; // Sprite para las nubes inferiores
  std::unique_ptr<MovingSprite> bottom_clouds_sprite_b_; // Sprite para las nubes inferiores

  std::unique_ptr<Sprite> buildings_sprite_; // Sprite con los edificios de fondo
  std::unique_ptr<Sprite> gradient_sprite_;  // Sprite con los graficos del degradado de color de fondo
  std::unique_ptr<Sprite> grass_sprite_;     // Sprite para la hierba

  SDL_Texture *canvas_;        // Textura para componer el fondo
  SDL_Texture *color_texture_; // Textura para atenuar el fondo

  // Variables
  SDL_Rect gradient_rect_[4];      // Vector con las coordenadas de los 4 degradados para el cielo
  SDL_Rect top_clouds_rect_[4];    // Vector con las coordenadas de los 4 nubes de arriba
  SDL_Rect bottom_clouds_rect_[4]; // Vector con las coordenadas de los 4 nubes de abajo
  int gradient_number_;            // Indica el número de degradado de fondo que se va a dibujar
  int alpha_;                      // Transparencia entre los dos degradados
  float clouds_speed_;             // Velocidad a la que se desplazan las nubes
  float transition_;               // Nivel de transición del fondo 0..1
  int counter_;                    // Contador interno
  SDL_Rect rect_;                  // Tamaño del objeto fondo
  SDL_Rect src_rect_;              // Parte del objeto fondo que se va a dibujará en pantalla
  SDL_Rect dst_rect_;              // Posición donde dibujar la parte del objeto fondo que se dibujará en pantalla
  int base_;                       // Linea de fondo coincidente con el area inferior de la zona de juego
  Color color_;                    // Color para atenuar el fondo
  int alpha_color_text_;           // Alpha para atenuar el fondo
  int alpha_color_text_temp_;      // Valor temporal para hacer la transición de alpha

  // Dibuja el gradiente de fondo
  void renderGradient();

  // Dibuja las nubes de arriba
  void renderTopClouds();

  // Dibuja las nubes de abajo
  void renderBottomClouds();

  // Compone todos los elementos del fondo en la textura
  void fillCanvas();

  // Actualiza el valor de alpha
  void updateAlphaColorText();

  // Actualiza las nubes
  void updateClouds();

public:
  // Constructor
  Background(SDL_Renderer *renderer);

  // Destructor
  ~Background();

  // Actualiza la lógica del objeto
  void update();

  // Dibuja el objeto
  void render();

  // Establece la posición del objeto
  void setPos(SDL_Rect pos);

  // Vuelve a cargar las texturas
  void reloadTextures();

  // Ajusta el valor de la variable
  void setCloudsSpeed(float value);

  // Ajusta el valor de la variable
  void setGradientNumber(int value);

  // Ajusta el valor de la variable
  void setTransition(float value);

  // Ajusta el valor de la variable
  void setSrcRect(SDL_Rect value);

  // Ajusta el valor de la variable
  void setDstRect(SDL_Rect value);

  // Establece el color de atenuación
  void setColor(Color color);

  // Establece la transparencia de la atenuación
  void setAlpha(int alpha);
};