#include "Star.h"
#include <math.h>
#include <iostream>
#include <cstdlib>

Star::Star() {
	height = 0;
	width = 0;
	radius = 0;
	SquareSide = 0;
	data = NULL;
}

Star::Star(std::vector<Point> vp) {
	height = 0;
	width = 0;
	SquareSide = 0;
	coordenates = vp;
	data = NULL;
}

std::vector<Point> Star::getCoordenates() {
	return coordenates;
}

Point Star::getCenter() {
	return center;
}

void Star::setMemory(int total_frames) {
	data = (double*)calloc((SquareSide * SquareSide) * total_frames, sizeof(double));
}

void Star::addData(std::vector<double> data, int frame) {

	int offset = (SquareSide * SquareSide) * frame;
	int i = 0;

	for (std::vector<double>::reverse_iterator itr = data.rbegin(); itr != data.rend(); itr++) {
		this->data[offset + i] = *itr;
		i++;
	}

}

double * Star::getData() {
	return this->data;
}

int Star::getHeight() {
	return height;
}

int Star::getWidth() {
	return width;
}

float Star::getRadius() {
	return radius;
}

int Star::getSquareSide() {
	return SquareSide;
}

void Star::setSquareSide(int val) {
	SquareSide = val;
}

void Star::FindParameters() {
	int max_x = -2147483647;
	int min_x = 2147483647;
	int max_y = -2147483647;
	int min_y = 2147483647;

	//Encontramos el punto mas alto y mas bajo en X y Y
	for (std::vector<Point>::iterator itr = coordenates.begin(); itr != coordenates.end(); itr++) {
		//Comparaciones en X
		if (itr->getX() > max_x) {
			max_x = itr->getX();
		}
		if (itr->getX() < min_x) {
			min_x = itr->getX();
		}
		//Comparaciones en Y
		if (itr->getY() > max_y) {
			max_y = itr->getY();
		}
		if (itr->getY() < min_y) {
			min_y = itr->getY();
		}
	}

	//Establecemos la altura
	width = (max_x - min_x) + 1;

	//Establecemos la anchura
	height = (max_y - min_y) + 1;

	//Establecemos un radio relativo a la altura y la anchura
	//radius = (sqrt(pow(height, 2) + pow(width, 2))) / 2;

	//Establecemos un radio relativo al lado mas largo de la estrella
	if (width > height) {
		radius = width;
	}
	else {
		radius = height;
	}

	//Buscamos el centro de la estrella
	int center_x, center_y;

	center_x = max_x - (width / 2);
	center_y = max_y - (height / 2);

	center.setX(center_x);
	center.setY(center_y);

	starting_center = center;
	prev_point = center;
}

void Star::addCenterInTime(Point c) {
	
	centers_in_time.push_back(c);

	point_x_in_time.push_back(c.getX() + 1);
	point_y_in_time.push_back(c.getY() + 1);

	//Movimiento Absoluto
	absolute_movement.push_back(starting_center.distance(c));

	//Movimiento Relativo
	relative_movement.push_back(prev_point.distance(c));

	//Cambiamos el punto previo al punto actual
	prev_point = c;

}

bool Star::InRadius(Point p, int radpct) {
	
	double distance = sqrt(pow((double)p.getX() - center.getX(),2) + pow((double)p.getY() - center.getY(),2));
	
	if (distance < (radius * radpct)) {
		return true;
	}
	else {
		return false;
	}
}

void Star::StarReset() {
	
	//Convertimos el ultimo centro conocido en el centro de la estrella actual
	std::vector<Point>::reverse_iterator itr = centers_in_time.rbegin();
	center = *itr;

	//Limpiamos memoria
	if (data) {
		free(data);
		data = NULL;
	}

	//Limpiamos la lista de centros y de puntos xy
	centers_in_time.clear();
	point_x_in_time.clear();
	point_y_in_time.clear();
	absolute_movement.clear();
	relative_movement.clear();
}

void Star::print() {
	std::cout << "Centro: (" << center.getX() << ", " << center.getY() << ")" << std::endl;
	//std::cout << "Altura: " << height << std::endl;
	//std::cout << "Anchura: " << width << std::endl;
}

void Star::PrintLastCenter() {
	
	std::vector<Point>::reverse_iterator itr = centers_in_time.rbegin();
	
	std::cout << "(" << itr->getX()+1 << ", " << itr->getY()+1 << ")" << std::endl;

}
