#include "item.h"
#include <stdlib.h>			 // Para rand
#include <algorithm>		 // Para clamp
#include "animated_sprite.h" // Para AnimatedSprite
#include "param.h"			 // Para Param, ParamGame, param
class Texture;				 // lines 6-6

Item::Item(ItemType type, float x, float y, SDL_FRect &play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
	: sprite_(std::make_unique<AnimatedSprite>(texture, animation)),
	  type_(type),
	  play_area_(play_area)
{
	switch (type)
	{
	case ItemType::COFFEE_MACHINE:
	{
		width_ = param.game.coffee_machine_w;
		height_ = param.game.coffee_machine_h;
		pos_x_ = (static_cast<int>(x + (play_area.w / 2)) % static_cast<int>(play_area.w - width_ - 5)) + 2;
		pos_y_ = y;
		vel_x_ = 0.0f;
		vel_y_ = -0.1f;
		accel_y_ = 0.1f;
		collider_.r = 10;
		break;
	}
	default:
	{
		width_ = param.game.item_size;
		height_ = param.game.item_size;
		pos_x_ = x;
		pos_y_ = y;
		vel_x_ = -1.0f + ((rand() % 5) * 0.5f);
		vel_y_ = -4.0f;
		accel_y_ = 0.2f;
		collider_.r = width_ / 2;
		break;
	}
	}

	// Actualiza el sprite
	shiftSprite();
	shiftColliders();
}

void Item::alignTo(int x)
{
	const float min_x = param.game.play_area.rect.x + 1;
	const float max_x = play_area_.w - width_ - 1;

	pos_x_ = x - (width_ / 2);

	// Ajusta para que no quede fuera de la zona de juego
	pos_x_ = std::clamp(pos_x_, min_x, max_x);

	// Actualiza el sprite
	shiftSprite();
	shiftColliders();
}

void Item::render()
{
	if (enabled_)
	{
		if (time_to_live_ > 200)
		{
			sprite_->render();
		}
		else if (time_to_live_ % 20 > 10)
		{
			sprite_->render();
		}
	}
}

void Item::move()
{
	floor_collision_ = false;

	// Calcula la nueva posición
	pos_x_ += vel_x_;
	pos_y_ += vel_y_;

	// Aplica las aceleraciones a la velocidad
	vel_x_ += accel_x_;
	vel_y_ += accel_y_;

	// Comprueba los laterales de la zona de juego
	const float min_x = param.game.play_area.rect.x;
	const float max_x = play_area_.w - width_;
	pos_x_ = std::clamp(pos_x_, min_x, max_x);

	// Si toca el borde lateral, invierte la velocidad horizontal
	if (pos_x_ == min_x || pos_x_ == max_x)
	{
		vel_x_ = -vel_x_;
	}

	// Si colisiona por arriba, rebota (excepto la máquina de café)
	if ((pos_y_ < param.game.play_area.rect.y) && !(type_ == ItemType::COFFEE_MACHINE))
	{
		// Corrige
		pos_y_ = param.game.play_area.rect.y;

		// Invierte la velocidad
		vel_y_ = -vel_y_;
	}

	// Si colisiona con la parte inferior
	if (pos_y_ > play_area_.h - height_)
	{
		// Corrige la posición
		pos_y_ = play_area_.h - height_;

		if (type_ == ItemType::COFFEE_MACHINE)
		{
			// Si es una máquina de café, detiene el objeto
			vel_y_ = vel_x_ = accel_x_ = accel_y_ = 0;
			floor_collision_ = true;
		}
		else
		{
			// Si no es una máquina de café
			if (vel_y_ < 1.0f)
			{
				// Si la velocidad vertical es baja, detiene el objeto
				vel_y_ = vel_x_ = accel_x_ = accel_y_ = 0;
			}
			else
			{
				// Si la velocidad vertical es alta, el objeto rebota y pierde velocidad
				vel_y_ *= -0.5f;
				vel_x_ *= 0.75f;
			}
		}
	}

	// Actualiza la posición del sprite
	shiftSprite();
	shiftColliders();
}

void Item::disable() { enabled_ = false; }

void Item::update()
{
	move();
	sprite_->update();
	updateTimeToLive();
}

void Item::updateTimeToLive()
{
	if (time_to_live_ > 0)
	{
		time_to_live_--;
	}
	else
	{
		disable();
	}
}

void Item::shiftColliders()
{
	collider_.x = static_cast<int>(pos_x_ + (width_ / 2));
	collider_.y = static_cast<int>(pos_y_ + (height_ / 2));
}

void Item::shiftSprite()
{
	sprite_->setPosX(pos_x_);
	sprite_->setPosY(pos_y_);
}
