#pragma once

#include <d2d1.h>

#include <cmath>

using namespace std;

const int CARD_WIDTH = 79;
const int CARD_HEIGHT = 109;

const int CARD_SPRITE_WIDTH = 79*2;
const int CARD_SPRITE_HEIGHT = 109*2;
const int CARD_SPRITE_MARGIN_X = 1*2;
const int CARD_SPRITE_MARGIN_Y = 1*2;

const float ANIMATION_SPEED = 2000.0f; // pixels per second

struct IPoint { int X; int Y; };
struct FPoint { float X; float Y; };

class Card {
public:
	int id;

	int index;
	int color;
	bool visible;

	uint64_t zIndex;

	int stack;
	int positionInStack;

	IPoint position;
	FPoint drawPosition;
	bool animating;

	// empty slot by default
	Card() : index(13), color(1), visible(true), drawPosition(0, 0) {
	}

	Card(int index, int color, bool visible) : index(index), color(color), visible(visible), drawPosition(0, 0) {
	}

	Card* clone() {
		Card* card = new Card();
		card->id = this->id;

		card->index = this->index;
		card->color = this->color;
		card->visible = this->visible;

		card->zIndex = this->zIndex;

		card->stack = this->stack;
		card->positionInStack = this->positionInStack;

		card->position = this->position;
		card->drawPosition = this->drawPosition;
		card->animating = this->animating;

		return card;
	}

	void resetDrawPosition() {
		drawPosition.X = (float)position.X;
		drawPosition.Y = (float)position.Y;
	}

	void update(float deltaTime) {
		if (animating) {
			float dx = position.X - drawPosition.X;
			float dy = position.Y - drawPosition.Y;
			float distance = sqrtf(dx * dx + dy * dy);

			float dirX = dx / distance;
			float dirY = dy / distance;

			float speed = ANIMATION_SPEED * deltaTime;
			if (distance <= speed) {
				drawPosition.X = (float)position.X;
				drawPosition.Y = (float)position.Y;
				animating = false;
			}
			else {
				drawPosition.X += dirX * speed;
				drawPosition.Y += dirY * speed;
			}
		}
	}

	void draw(ID2D1RenderTarget* rt, ID2D1Bitmap* cardsSheet) {
		int indexX, indexY;
		if (this->visible) {
			indexX = this->index;
			indexY = this->color;
		}
		else {
			indexX = 13;
			indexY = 0;
		}

		D2D1_RECT_F destRect = D2D1::RectF(drawPosition.X, drawPosition.Y, drawPosition.X + CARD_WIDTH, drawPosition.Y + CARD_HEIGHT);

		float bgsrcLeft = (float)(13 * (CARD_SPRITE_WIDTH + CARD_SPRITE_MARGIN_X));
		float bgsrcTop = (float)(2 * (CARD_SPRITE_HEIGHT + CARD_SPRITE_MARGIN_Y));
		D2D1_RECT_F bgsrcRect = D2D1::RectF(bgsrcLeft, bgsrcTop, bgsrcLeft + CARD_SPRITE_WIDTH, bgsrcTop + CARD_SPRITE_HEIGHT);

		rt->DrawBitmap(cardsSheet, destRect, 1.0f, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &bgsrcRect);

		float srcLeft = (float)(indexX * (CARD_SPRITE_WIDTH + CARD_SPRITE_MARGIN_X));
		float srcTop = (float)(indexY * (CARD_SPRITE_HEIGHT + CARD_SPRITE_MARGIN_Y));
		D2D1_RECT_F srcRect = D2D1::RectF(srcLeft, srcTop, srcLeft + CARD_SPRITE_WIDTH, srcTop + CARD_SPRITE_HEIGHT);

		rt->DrawBitmap(cardsSheet, destRect, 1.0f, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &srcRect);
	}
};
