#include "const.h"
#include "item.h"

// Constructor
Item::Item(LTexture *texture, SDL_Renderer *renderer, Uint8 type, float x, float y)
{
	mSprite = new AnimatedSprite(texture, renderer);

	mClass = type;
	mEnabled = true;
	mTimeToLive = 600;
	mPosX = x;
	mPosY = y;
	mWidth = 16;
	mHeight = 16;
	mVelX = -1.0f + ((rand() % 5) * 0.5f);
	mVelY = -4.0f;
	mAccelX = 0.0f;
	mAccelY = 0.2f;
	mFloorCollision = false;
	mCollider.r = mWidth / 2;
	shiftColliders();

	mSprite->setAnimationFrames(0, 0, 0, 48, mWidth, mHeight);
	mSprite->setAnimationFrames(0, 1, 0, 64, mWidth, mHeight);
	mSprite->setCurrentFrame(0);
	mSprite->setAnimationCounter(0);
	mSprite->setAnimationSpeed(0, 10);
	mSprite->setAnimationLoop(0, true);
	mSprite->setSpriteClip(mSprite->getAnimationClip(0, 0));
	mSprite->setPosX(mPosX);
	mSprite->setPosY(mPosY);

	switch (type)
	{
	case NO_KIND:
		mEnabled = false;
		mTimeToLive = 0;
		mPosX = 0;
		mPosY = 0;
		mWidth = 0;
		mHeight = 0;
		mVelX = 0;
		mVelY = 0;
		break;

	case ITEM_POINTS_1_DISK:
		mSprite->setAnimationFrames(0, 0, 16 * 0, 16 * 0, mWidth, mHeight);
		mSprite->setAnimationFrames(0, 1, 16 * 0, 16 * 1, mWidth, mHeight);
		break;

	case ITEM_POINTS_2_GAVINA:
		mSprite->setAnimationFrames(0, 0, 16 * 1, 16 * 0, mWidth, mHeight);
		mSprite->setAnimationFrames(0, 1, 16 * 1, 16 * 1, mWidth, mHeight);
		break;

	case ITEM_POINTS_3_PACMAR:
		mSprite->setAnimationFrames(0, 0, 16 * 2, 16 * 0, mWidth, mHeight);
		mSprite->setAnimationFrames(0, 1, 16 * 2, 16 * 1, mWidth, mHeight);
		break;

	case ITEM_CLOCK:
		mSprite->setAnimationFrames(0, 0, 16 * 3, 16 * 0, mWidth, mHeight);
		mSprite->setAnimationFrames(0, 1, 16 * 3, 16 * 1, mWidth, mHeight);
		break;

	case ITEM_COFFEE:
		mSprite->setAnimationFrames(0, 0, 16 * 5, 16 * 0, mWidth, mHeight);
		mSprite->setAnimationFrames(0, 1, 16 * 5, 16 * 1, mWidth, mHeight);
		break;

	case ITEM_COFFEE_MACHINE:
		mWidth = 32;
		mHeight = 32;
		mPosX = (((int)x + (PLAY_AREA_WIDTH / 2)) % (PLAY_AREA_WIDTH - mWidth - 5)) + 2;
		mPosY = PLAY_AREA_TOP - mHeight;
		mVelX = 0.0f;
		mVelY = -0.1f;
		mAccelY = 0.1f;
		mSprite->setAnimationFrames(0, 0, 32 * 0, 16 * 2, mWidth, mHeight);
		mSprite->setAnimationFrames(0, 1, 32 * 1, 16 * 2, mWidth, mHeight);
		mSprite->setAnimationFrames(0, 2, 32 * 2, 16 * 2, mWidth, mHeight);
		mSprite->setAnimationFrames(0, 3, 32 * 3, 16 * 2, mWidth, mHeight);
		mSprite->setPosX(mPosX);
		mSprite->setPosY(mPosY);
		mCollider.r = 10;
		shiftColliders();
		break;

	default:
		break;
	}
}

// Destructor
Item::~Item()
{
	delete mSprite;
	mSprite = nullptr;
}

// Centra el objeto en la posición X
void Item::allignTo(int x)
{
	mPosX = float(x - (mWidth / 2));

	if (mPosX < PLAY_AREA_LEFT)
	{
		mPosX = PLAY_AREA_LEFT + 1;
	}
	else if ((mPosX + mWidth) > PLAY_AREA_RIGHT)
	{
		mPosX = float(PLAY_AREA_RIGHT - mWidth - 1);
	}

	// Posición X,Y del sprite
	mSprite->setPosX(int(mPosX));
	mSprite->setPosY(int(mPosY));

	// Alinea el circulo de colisión con el objeto
	shiftColliders();
}

// Pinta el objeto en la pantalla
void Item::render()
{
	if (mEnabled)
	{
		if (mTimeToLive > 200)
		{
			mSprite->render();
		}
		else if (mTimeToLive % 20 > 10)
		{
			mSprite->render();
		}
	}
}

// Actualiza la posición y estados del objeto
void Item::move()
{
	mFloorCollision = false;

	// Calcula la nueva posición
	mPosX += mVelX;
	mPosY += mVelY;

	// Aplica las aceleraciones a la velocidad
	mVelX += mAccelX;
	mVelY += mAccelY;

	// Si queda fuera de pantalla, corregimos su posición y cambiamos su sentido
	if ((mPosX < PLAY_AREA_LEFT) || (mPosX + mWidth > PLAY_AREA_RIGHT))
	{
		// Corregir posición
		mPosX -= mVelX;

		// Invertir sentido
		mVelX = -mVelX;
	}

	// Si se sale por arriba rebota (excepto la maquina de café)
	if ((mPosY < PLAY_AREA_TOP) && !(mClass == ITEM_COFFEE_MACHINE))
	{
		// Corrige
		mPosY = PLAY_AREA_TOP;

		// Invierte el sentido
		mVelY = -mVelY;
	}

	// Si el objeto se sale por la parte inferior
	if (mPosY + mHeight > PLAY_AREA_BOTTOM)
	{
		// Corrige
		mPosY -= mVelY;

		// Detiene el objeto
		mVelY = 0;
		mVelX = 0;
		mAccelX = 0;
		mAccelY = 0;
		mPosY = PLAY_AREA_BOTTOM - mHeight;
		if (mClass == ITEM_COFFEE_MACHINE)
			mFloorCollision = true;
	}

	// Actualiza la posición del sprite
	mSprite->setPosX(int(mPosX));
	mSprite->setPosY(int(mPosY));
}

// Pone a cero todos los valores del objeto
void Item::erase()
{
	// init(NO_KIND, 0, 0, nullptr, nullptr);
}

// Actualiza el objeto a su posicion, animación y controla los contadores
void Item::update()
{
	if (mEnabled)
	{
		move();
		shiftColliders();
		mSprite->animate();
		updateTimeToLive();
		checkTimeToLive();
	}
}

// Actualiza el contador
void Item::updateTimeToLive()
{
	if (mTimeToLive > 0)
	{
		mTimeToLive--;
	}
}

// Comprueba si el objeto sigue vivo
void Item::checkTimeToLive()
{
	if (mTimeToLive == 0)
		erase();
}

// Obtiene del valor de la variable
float Item::getPosX()
{
	return mPosX;
}

// Obtiene del valor de la variable
float Item::getPosY()
{
	return mPosY;
}

// Obtiene del valor de la variable
int Item::getWidth()
{
	return mWidth;
}

// Obtiene del valor de la variable
int Item::getHeight()
{
	return mHeight;
}

// Obtiene del valor de la variable
int Item::getClass()
{
	return mClass;
}

// Obtiene el valor de la variable
bool Item::isEnabled()
{
	return mEnabled;
}

// Establece el valor de la variable
void Item::setEnabled(bool value)
{
	mEnabled = value;
}

// Obtiene el circulo de colisión
circle_t &Item::getCollider()
{
	return mCollider;
}

// Alinea el circulo de colisión con la posición del objeto
void Item::shiftColliders()
{
	mCollider.x = int(mPosX + (mWidth / 2));
	mCollider.y = int(mPosY + (mHeight / 2));
}

// Informa si el objeto ha colisionado con el suelo
bool Item::floorCollision()
{
	return mFloorCollision;
}